From: Gabriel Ramos Barbosa Mota <maguraa53@gmail.com>
To: davem@davemloft.net, kuba@kernel.org, deller@gmx.de,
fero@drama.obuda.kando.hu
Cc: netdev@vger.kernel.org, linux-fbdev@vger.kernel.org,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
Gabriel Ramos Barbosa Mota <maguraa53@gmail.com>
Subject: [PATCH] drivers: net and video: remove legacy 16-bit and non-x86 hardware drivers
Date: Sat, 13 Jun 2026 00:31:30 -0300 [thread overview]
Message-ID: <20260613033138.601841-1-maguraa53@gmail.com> (raw)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 614455 bytes --]
---
drivers/net/ethernet/3com/3c509.c | 1543 ---------
drivers/net/ethernet/3com/Makefile | 1 -
drivers/net/ethernet/3com/Makefile.save | 7 +
drivers/net/ethernet/8390/Makefile | 14 +-
drivers/net/ethernet/8390/apne.c | 614 ----
drivers/net/ethernet/8390/ax88796.c | 1022 ------
drivers/net/ethernet/8390/etherh.c | 858 -----
drivers/net/ethernet/8390/hydra.c | 274 --
drivers/net/ethernet/8390/mac8390.c | 848 -----
drivers/net/ethernet/8390/mcf8390.c | 468 ---
drivers/net/ethernet/8390/ne.c | 992 ------
drivers/net/ethernet/8390/pcnet_cs.c | 1717 ----------
drivers/net/ethernet/8390/stnic.c | 300 --
drivers/net/ethernet/8390/xsurf100.c | 377 ---
drivers/net/ethernet/8390/zorro8390.c | 447 ---
drivers/video/fbdev/Makefile | 10 +-
drivers/video/fbdev/acornfb.c | 1102 -------
drivers/video/fbdev/acornfb.h | 166 -
drivers/video/fbdev/amifb.c | 3787 -----------------------
drivers/video/fbdev/atafb.c | 3188 -------------------
drivers/video/fbdev/atafb.h | 37 -
drivers/video/fbdev/atafb_iplan2p2.c | 270 --
drivers/video/fbdev/atafb_iplan2p4.c | 285 --
drivers/video/fbdev/atafb_iplan2p8.c | 322 --
drivers/video/fbdev/atafb_mfb.c | 89 -
drivers/video/fbdev/atafb_utils.h | 401 ---
drivers/video/fbdev/hgafb.c | 685 ----
drivers/video/fbdev/vga16fb.c | 1442 ---------
28 files changed, 19 insertions(+), 21247 deletions(-)
delete mode 100644 drivers/net/ethernet/3com/3c509.c
create mode 100644 drivers/net/ethernet/3com/Makefile.save
delete mode 100644 drivers/net/ethernet/8390/apne.c
delete mode 100644 drivers/net/ethernet/8390/ax88796.c
delete mode 100644 drivers/net/ethernet/8390/etherh.c
delete mode 100644 drivers/net/ethernet/8390/hydra.c
delete mode 100644 drivers/net/ethernet/8390/mac8390.c
delete mode 100644 drivers/net/ethernet/8390/mcf8390.c
delete mode 100644 drivers/net/ethernet/8390/ne.c
delete mode 100644 drivers/net/ethernet/8390/pcnet_cs.c
delete mode 100644 drivers/net/ethernet/8390/stnic.c
delete mode 100644 drivers/net/ethernet/8390/xsurf100.c
delete mode 100644 drivers/net/ethernet/8390/zorro8390.c
delete mode 100644 drivers/video/fbdev/acornfb.c
delete mode 100644 drivers/video/fbdev/acornfb.h
delete mode 100644 drivers/video/fbdev/amifb.c
delete mode 100644 drivers/video/fbdev/atafb.c
delete mode 100644 drivers/video/fbdev/atafb.h
delete mode 100644 drivers/video/fbdev/atafb_iplan2p2.c
delete mode 100644 drivers/video/fbdev/atafb_iplan2p4.c
delete mode 100644 drivers/video/fbdev/atafb_iplan2p8.c
delete mode 100644 drivers/video/fbdev/atafb_mfb.c
delete mode 100644 drivers/video/fbdev/atafb_utils.h
delete mode 100644 drivers/video/fbdev/hgafb.c
delete mode 100644 drivers/video/fbdev/vga16fb.c
diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c
deleted file mode 100644
index f23be7425..000000000
--- a/drivers/net/ethernet/3com/3c509.c
+++ /dev/null
@@ -1,1543 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
-/*
- * Written 1993-2000 by Donald Becker.
- *
- * Copyright 1994-2000 by Donald Becker.
- * Copyright 1993 United States Government as represented by the
- * Director, National Security Agency. This software may be used and
- * distributed according to the terms of the GNU General Public License,
- * incorporated herein by reference.
- *
- * This driver is for the 3Com EtherLinkIII series.
- *
- * The author may be reached as becker@scyld.com, or C/O
- * Scyld Computing Corporation
- * 410 Severn Ave., Suite 210
- * Annapolis MD 21403
- *
- * Known limitations:
- * Because of the way 3c509 ISA detection works it's difficult to predict
- * a priori which of several ISA-mode cards will be detected first.
- *
- * This driver does not use predictive interrupt mode, resulting in higher
- * packet latency but lower overhead. If interrupts are disabled for an
- * unusually long time it could also result in missed packets, but in
- * practice this rarely happens.
- *
- *
- * FIXES:
- * Alan Cox: Removed the 'Unexpected interrupt' bug.
- * Michael Meskes: Upgraded to Donald Becker's version 1.07.
- * Alan Cox: Increased the eeprom delay. Regardless of
- * what the docs say some people definitely
- * get problems with lower (but in card spec)
- * delays.
- * v1.10 4/21/97 Fixed module code so that multiple cards may be
- * detected, other cleanups. -djb
- * Andrea Arcangeli: Upgraded to Donald Becker's version 1.12.
- * Rick Payne: Fixed SMP race condition.
- * v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable
- * variable. -djb
- * v1.14 10/15/97 Avoided waiting..discard message for fast
- * machines. -djb
- * v1.15 1/31/98 Faster recovery for Tx errors. -djb
- * v1.16 2/3/98 Different ID port handling to avoid sound
- * cards. -djb
- * v1.18 12Mar2001 Andrew Morton
- * - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
- * - Reviewed against 1.18 from scyld.com
- * v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
- * - ethtool support.
- * v1.18b 1Mar2002 Zwane Mwaikambo <zwane@commfireservices.com>
- * - Power Management support.
- * v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
- * - Full duplex support.
- * v1.19 16Oct2002 Zwane Mwaikambo <zwane@linuxpower.ca>
- * - Additional ethtool features.
- * v1.19a 28Oct2002 David Ruggiero <jdr@farfalle.com>
- * - Increase *read_eeprom udelay to workaround oops with
- * 2 cards.
- * v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
- * - Introduce driver model for EISA cards.
- * v1.20 04Feb2008 Ondrej Zary <linux@rainbow-software.org>
- * - convert to isa_driver and pnp_driver and some
- * cleanups.
- */
-
-#define DRV_NAME "3c509"
-
-/* A few values that may be tweaked. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (400 * HZ / 1000)
-
-#include <linux/bitops.h>
-#include <linux/delay.h> /* for udelay() */
-#include <linux/device.h>
-#include <linux/eisa.h>
-#include <linux/errno.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/in.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/isa.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pm.h>
-#include <linux/pnp.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/uaccess.h>
-
-#include <asm/irq.h>
-
-#ifdef EL3_DEBUG
-static int el3_debug = EL3_DEBUG;
-#else
-static int el3_debug = 2;
-#endif
-
-/* Used to do a global count of all the cards in the system. Must be
- * a global variable so that the eisa probe routines can increment it.
- */
-static int el3_cards;
-#define EL3_MAX_CARDS 8
-
-/* To minimize the size of the driver source I only define operating
- * constants if they are used several times. You'll need the manual
- * anyway if you want to understand driver details.
- */
-/* Offsets from base I/O address. */
-#define EL3_DATA 0x00
-#define EL3_CMD 0x0e
-#define EL3_STATUS 0x0e
-#define EEPROM_READ 0x80
-
-#define EL3_IO_EXTENT 16
-
-#define EL3WINDOW(win_num) outw(SELECT_WINDOW + (win_num), ioaddr + EL3_CMD)
-
-/* The top five bits written to EL3_CMD are a command, the lower
- * 11 bits are the parameter, if applicable.
- */
-enum c509cmd {
- TOTAL_RESET = 0 << 11,
- SELECT_WINDOW = 1 << 11,
- START_COAX = 2 << 11,
- RX_DISABLE = 3 << 11,
- RX_ENABLE = 4 << 11,
- RX_RESET = 5 << 11,
- RX_DISCARD = 8 << 11,
- TX_ENABLE = 9 << 11,
- TX_DISABLE = 10 << 11,
- TX_RESET = 11 << 11,
- FAKE_INTR = 12 << 11,
- ACK_INTR = 13 << 11,
- SET_INTR_ENB = 14 << 11,
- SET_STATUS_ENB = 15 << 11,
- SET_RX_FILTER = 16 << 11,
- SET_RX_THRESHOLD = 17 << 11,
- SET_TX_THRESHOLD = 18 << 11,
- SET_TX_START = 19 << 11,
- STATS_ENABLE = 21 << 11,
- STATS_DISABLE = 22 << 11,
- STOP_COAX = 23 << 11,
- POWER_UP = 27 << 11,
- POWER_DOWN = 28 << 11,
- POWER_AUTO = 29 << 11,
-};
-
-enum c509status {
- INT_LATCH = 0x0001,
- ADAPTER_FAILURE = 0x0002,
- TX_COMPLETE = 0x0004,
- TX_AVAILABLE = 0x0008,
- RX_COMPLETE = 0x0010,
- RX_EARLY = 0x0020,
- INT_REQ = 0x0040,
- STATS_FULL = 0x0080,
- CMD_BUSY = 0x1000,
-};
-
-/* The SET_RX_FILTER command accepts the following classes: */
-enum rx_filter {
- RX_STATION = 1,
- RX_MULTICAST = 2,
- RX_BROADCAST = 4,
- RX_PROM = 8,
-};
-
-/* Register window 1 offsets, the window used in normal operation. */
-#define TX_FIFO 0x00
-#define RX_FIFO 0x00
-#define RX_STATUS 0x08
-#define TX_STATUS 0x0B
-#define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */
-
-#define WN0_CONF_CTRL 0x04 /* Window 0: Configuration control register. */
-#define WN0_ADDR_CONF 0x06 /* Window 0: Address configuration register. */
-#define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */
-#define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */
-#define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
-#define WN4_NETDIAG 0x06 /* Window 4: Net diagnostic. */
-#define FD_ENABLE 0x8000 /* Enable full-duplex ("external loopback"). */
-
-/*
- * Must be a power of two (we use a binary and in the
- * circular queue).
- */
-#define SKB_QUEUE_SIZE 64
-
-enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_EISA };
-
-struct el3_private {
- /* for device access */
- spinlock_t lock;
- /* skb send-queue */
- int head, size;
- struct sk_buff *queue[SKB_QUEUE_SIZE];
- enum el3_cardtype type;
-};
-
-static int id_port;
-static int current_tag;
-static struct net_device *el3_devs[EL3_MAX_CARDS];
-
-/* Parameters that may be passed into the module. */
-static int debug = -1;
-static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 10;
-#ifdef CONFIG_PNP
-static int nopnp;
-#endif
-
-static int el3_common_init(struct net_device *dev);
-static void el3_common_remove(struct net_device *dev);
-static ushort id_read_eeprom(int index);
-static ushort read_eeprom(int ioaddr, int index);
-static int el3_open(struct net_device *dev);
-static netdev_tx_t el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el3_interrupt(int irq, void *dev_id);
-static void update_stats(struct net_device *dev);
-static struct net_device_stats *el3_get_stats(struct net_device *dev);
-static int el3_rx(struct net_device *dev);
-static int el3_close(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-static void el3_tx_timeout(struct net_device *dev, unsigned int txqueue);
-static void el3_down(struct net_device *dev);
-static void el3_up(struct net_device *dev);
-static const struct ethtool_ops ethtool_ops;
-#ifdef CONFIG_PM
-static int el3_suspend(struct device *, pm_message_t);
-static int el3_resume(struct device *);
-#else
-#define el3_suspend NULL
-#define el3_resume NULL
-#endif
-
-/* Generic device remove for all device types. */
-static int el3_device_remove(struct device *device);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void el3_poll_controller(struct net_device *dev);
-#endif
-
-/* Return 0 on success, 1 on error, 2 when found already detected PnP card. */
-static int el3_isa_id_sequence(__be16 *phys_addr)
-{
- short lrs_state = 0xff;
- int i;
-
- /* ISA boards are detected 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
- * respond to subsequent ID sequences.
- */
- outb(0x00, id_port);
- outb(0x00, id_port);
- for (i = 0; i < 255; i++) {
- outb(lrs_state, id_port);
- lrs_state <<= 1;
- lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
- }
- /* For the first probe, clear all board's tag registers. */
- if (current_tag == 0)
- outb(0xd0, id_port);
- else /* Otherwise kill off already-found boards. */
- outb(0xd8, id_port);
- if (id_read_eeprom(7) != 0x6d50)
- return 1;
- /* Read in EEPROM data, which does contention-select.
- * Only the lowest address board will stay "on-line".
- * 3Com got the byte order backwards.
- */
- for (i = 0; i < 3; i++)
- phys_addr[i] = htons(id_read_eeprom(i));
-#ifdef CONFIG_PNP
- if (!nopnp) {
- /* The ISA PnP 3c509 cards respond to the ID sequence too.
- * This check is needed in order not to register them twice.
- */
- for (i = 0; i < el3_cards; i++) {
- struct el3_private *lp = netdev_priv(el3_devs[i]);
-
- if (lp->type == EL3_PNP &&
- ether_addr_equal((u8 *)phys_addr,
- el3_devs[i]->dev_addr)) {
- if (el3_debug > 3)
- pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
- phys_addr[0] & 0xff,
- phys_addr[0] >> 8,
- phys_addr[1] & 0xff,
- phys_addr[1] >> 8,
- phys_addr[2] & 0xff,
- phys_addr[2] >> 8);
- /* Set the adaptor tag so that the next card
- * can be found.
- */
- outb(0xd0 + ++current_tag, id_port);
- return 2;
- }
- }
- }
-#endif /* CONFIG_PNP */
- return 0;
-}
-
-static void el3_dev_fill(struct net_device *dev, __be16 *phys_addr, int ioaddr,
- int irq, int if_port, enum el3_cardtype type)
-{
- struct el3_private *lp = netdev_priv(dev);
-
- eth_hw_addr_set(dev, (u8 *)phys_addr);
- dev->base_addr = ioaddr;
- dev->irq = irq;
- dev->if_port = if_port;
- lp->type = type;
-}
-
-static int el3_isa_match(struct device *pdev, unsigned int ndev)
-{
- int ioaddr, isa_irq, if_port, err;
- struct net_device *dev;
- unsigned int iobase;
- __be16 phys_addr[3];
-
- while ((err = el3_isa_id_sequence(phys_addr)) == 2)
- ; /* Skip to next card when PnP card found */
- if (err == 1)
- return 0;
-
- iobase = id_read_eeprom(8);
- if_port = iobase >> 14;
- ioaddr = 0x200 + ((iobase & 0x1f) << 4);
- if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
- isa_irq = irq[el3_cards];
- else
- isa_irq = id_read_eeprom(9) >> 12;
-
- dev = alloc_etherdev(sizeof(struct el3_private));
- if (!dev)
- return -ENOMEM;
-
- SET_NETDEV_DEV(dev, pdev);
-
- if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
- free_netdev(dev);
- return 0;
- }
-
- /* Set the adaptor tag so that the next card can be found. */
- outb(0xd0 + ++current_tag, id_port);
-
- /* Activate the adaptor at the EEPROM location. */
- outb((ioaddr >> 4) | 0xe0, id_port);
-
- EL3WINDOW(0);
- if (inw(ioaddr) != 0x6d50) {
- free_netdev(dev);
- return 0;
- }
-
- /* Free the interrupt so that some other card can use it. */
- outw(0x0f00, ioaddr + WN0_IRQ);
-
- el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
- dev_set_drvdata(pdev, dev);
- if (el3_common_init(dev)) {
- free_netdev(dev);
- return 0;
- }
-
- el3_devs[el3_cards++] = dev;
- return 1;
-}
-
-static void el3_isa_remove(struct device *pdev, unsigned int ndev)
-{
- el3_device_remove(pdev);
- dev_set_drvdata(pdev, NULL);
-}
-
-#ifdef CONFIG_PM
-static int el3_isa_suspend(struct device *dev, unsigned int n,
- pm_message_t state)
-{
- current_tag = 0;
- return el3_suspend(dev, state);
-}
-
-static int el3_isa_resume(struct device *dev, unsigned int n)
-{
- struct net_device *ndev = dev_get_drvdata(dev);
- int ioaddr = ndev->base_addr, err;
- __be16 phys_addr[3];
-
- while ((err = el3_isa_id_sequence(phys_addr)) == 2)
- ; /* Skip to next card when PnP card found */
- if (err == 1)
- return 0;
- /* Set the adaptor tag so that the next card can be found. */
- outb(0xd0 + ++current_tag, id_port);
- /* Enable the card */
- outb((ioaddr >> 4) | 0xe0, id_port);
- EL3WINDOW(0);
- if (inw(ioaddr) != 0x6d50)
- return 1;
- /* Free the interrupt so that some other card can use it. */
- outw(0x0f00, ioaddr + WN0_IRQ);
- return el3_resume(dev);
-}
-#endif
-
-static struct isa_driver el3_isa_driver = {
- .match = el3_isa_match,
- .remove = el3_isa_remove,
-#ifdef CONFIG_PM
- .suspend = el3_isa_suspend,
- .resume = el3_isa_resume,
-#endif
- .driver = {
- .name = "3c509"
- },
-};
-
-static int isa_registered;
-
-#ifdef CONFIG_PNP
-static const struct pnp_device_id el3_pnp_ids[] = {
- { .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
- { .id = "TCM5091" }, /* 3Com Etherlink III */
- { .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
- { .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
- { .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
- { .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
- { .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
- { .id = "" }
-};
-MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
-
-static int el3_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
-{
- struct net_device *dev = NULL;
- int ioaddr, irq, if_port;
- __be16 phys_addr[3];
- short i;
- int err;
-
- ioaddr = pnp_port_start(pdev, 0);
- if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
- return -EBUSY;
- irq = pnp_irq(pdev, 0);
- EL3WINDOW(0);
- for (i = 0; i < 3; i++)
- phys_addr[i] = htons(read_eeprom(ioaddr, i));
- if_port = read_eeprom(ioaddr, 8) >> 14;
- dev = alloc_etherdev(sizeof(struct el3_private));
- if (!dev) {
- release_region(ioaddr, EL3_IO_EXTENT);
- return -ENOMEM;
- }
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
- pnp_set_drvdata(pdev, dev);
- err = el3_common_init(dev);
-
- if (err) {
- pnp_set_drvdata(pdev, NULL);
- free_netdev(dev);
- return err;
- }
-
- el3_devs[el3_cards++] = dev;
- return 0;
-}
-
-static void el3_pnp_remove(struct pnp_dev *pdev)
-{
- el3_common_remove(pnp_get_drvdata(pdev));
- pnp_set_drvdata(pdev, NULL);
-}
-
-#ifdef CONFIG_PM
-static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
-{
- return el3_suspend(&pdev->dev, state);
-}
-
-static int el3_pnp_resume(struct pnp_dev *pdev)
-{
- return el3_resume(&pdev->dev);
-}
-#endif
-
-static struct pnp_driver el3_pnp_driver = {
- .name = "3c509",
- .id_table = el3_pnp_ids,
- .probe = el3_pnp_probe,
- .remove = el3_pnp_remove,
-#ifdef CONFIG_PM
- .suspend = el3_pnp_suspend,
- .resume = el3_pnp_resume,
-#endif
-};
-
-static int pnp_registered;
-#endif /* CONFIG_PNP */
-
-#ifdef CONFIG_EISA
-static const struct eisa_device_id el3_eisa_ids[] = {
- { "TCM5090" },
- { "TCM5091" },
- { "TCM5092" },
- { "TCM5093" },
- { "TCM5094" },
- { "TCM5095" },
- { "TCM5098" },
- { "" }
-};
-MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
-
-static int el3_eisa_probe(struct device *device);
-
-static struct eisa_driver el3_eisa_driver = {
- .id_table = el3_eisa_ids,
- .driver = {
- .name = "3c579",
- .probe = el3_eisa_probe,
- .remove = el3_device_remove,
- .suspend = el3_suspend,
- .resume = el3_resume,
- }
-};
-
-static int eisa_registered;
-#endif
-
-static const struct net_device_ops netdev_ops = {
- .ndo_open = el3_open,
- .ndo_stop = el3_close,
- .ndo_start_xmit = el3_start_xmit,
- .ndo_get_stats = el3_get_stats,
- .ndo_set_rx_mode = set_multicast_list,
- .ndo_tx_timeout = el3_tx_timeout,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = el3_poll_controller,
-#endif
-};
-
-static int el3_common_init(struct net_device *dev)
-{
- static const char *const if_names[] = {
- "10baseT", "AUI", "undefined", "BNC"
- };
- struct el3_private *lp = netdev_priv(dev);
- int err;
-
- spin_lock_init(&lp->lock);
-
- if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
- dev->if_port = (dev->mem_start & 0x0f);
- } else { /* xcvr codes 0/8 */
- /* use eeprom value, but save user's full-duplex selection */
- dev->if_port |= (dev->mem_start & 0x08);
- }
-
- /* The EL3-specific entries in the device structure. */
- dev->netdev_ops = &netdev_ops;
- dev->watchdog_timeo = TX_TIMEOUT;
- dev->ethtool_ops = ðtool_ops;
-
- err = register_netdev(dev);
- if (err) {
- pr_err("Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n",
- dev->base_addr, dev->irq);
- release_region(dev->base_addr, EL3_IO_EXTENT);
- return err;
- }
-
- pr_info("%s: 3c5x9 found at %#3.3lx, %s port, address %pM, IRQ %d.\n",
- dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
- dev->dev_addr, dev->irq);
-
- return 0;
-}
-
-static void el3_common_remove(struct net_device *dev)
-{
- unregister_netdev(dev);
- release_region(dev->base_addr, EL3_IO_EXTENT);
- free_netdev(dev);
-}
-
-#ifdef CONFIG_EISA
-static int el3_eisa_probe(struct device *device)
-{
- struct net_device *dev = NULL;
- struct eisa_device *edev;
- int ioaddr, irq, if_port;
- __be16 phys_addr[3];
- short i;
- int err;
-
- /* Yeepee, The driver framework is calling us ! */
- edev = to_eisa_device(device);
- ioaddr = edev->base_addr;
-
- if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
- return -EBUSY;
-
- /* Change the register set to the configuration window 0. */
- outw(SELECT_WINDOW | 0, ioaddr + 0xC80 + EL3_CMD);
-
- irq = inw(ioaddr + WN0_IRQ) >> 12;
- if_port = inw(ioaddr + 6) >> 14;
- for (i = 0; i < 3; i++)
- phys_addr[i] = htons(read_eeprom(ioaddr, i));
-
- /* Restore the "Product ID" to the EEPROM read register. */
- read_eeprom(ioaddr, 3);
-
- dev = alloc_etherdev(sizeof(struct el3_private));
- if (!dev) {
- release_region(ioaddr, EL3_IO_EXTENT);
- return -ENOMEM;
- }
-
- SET_NETDEV_DEV(dev, device);
-
- el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
- eisa_set_drvdata(edev, dev);
- err = el3_common_init(dev);
-
- if (err) {
- eisa_set_drvdata(edev, NULL);
- free_netdev(dev);
- return err;
- }
-
- el3_devs[el3_cards++] = dev;
- return 0;
-}
-#endif
-
-/* This remove works for all device types.
- *
- * The net dev must be stored in the driver data field.
- */
-static int el3_device_remove(struct device *device)
-{
- struct net_device *dev;
-
- dev = dev_get_drvdata(device);
-
- el3_common_remove(dev);
- return 0;
-}
-
-/* Read a word from the EEPROM using the regular EEPROM access register.
- * Assume that we are in register window zero.
- */
-static ushort read_eeprom(int ioaddr, int index)
-{
- outw(EEPROM_READ + index, ioaddr + 10);
- /* Pause for at least 162 us for the read to take place.
- * Some chips seem to require much longer.
- */
- mdelay(2);
- return inw(ioaddr + 12);
-}
-
-/* Read a word from the EEPROM when in the ISA ID probe state. */
-static ushort id_read_eeprom(int index)
-{
- int bit, word = 0;
-
- /* Issue read command, and pause for at least 162 us for it to
- * complete. Assume extra-fast 16MHz bus.
- */
- outb(EEPROM_READ + index, id_port);
-
- /* Pause for at least 162 us for the read to take place.
- * Some chips seem to require much longer.
- */
- mdelay(4);
-
- for (bit = 15; bit >= 0; bit--)
- word = (word << 1) + (inb(id_port) & 0x01);
-
- if (el3_debug > 3)
- pr_debug(" 3c509 EEPROM word %d %#4.4x.\n", index, word);
-
- return word;
-}
-
-static int el3_open(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
- int i;
-
- outw(TX_RESET, ioaddr + EL3_CMD);
- outw(RX_RESET, ioaddr + EL3_CMD);
- outw(SET_STATUS_ENB | 0x00, ioaddr + EL3_CMD);
-
- i = request_irq(dev->irq, el3_interrupt, 0, dev->name, dev);
- if (i)
- return i;
-
- EL3WINDOW(0);
- if (el3_debug > 3)
- pr_debug("%s: Opening, IRQ %d status@%x %4.4x.\n",
- dev->name, dev->irq,
- ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
-
- el3_up(dev);
-
- if (el3_debug > 3)
- pr_debug("%s: Opened 3c509 IRQ %d status %4.4x.\n",
- dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
-
- return 0;
-}
-
-static void el3_tx_timeout(struct net_device *dev, unsigned int txqueue)
-{
- int ioaddr = dev->base_addr;
-
- /* Transmitter timeout, serious problems. */
- pr_warn("%s: transmit timed out, Tx_status %2.2x status %4.4x Tx FIFO room %d\n",
- dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
- inw(ioaddr + TX_FREE));
- dev->stats.tx_errors++;
- netif_trans_update(dev); /* prevent tx timeout */
- /* Issue TX_RESET and TX_START commands. */
- outw(TX_RESET, ioaddr + EL3_CMD);
- outw(TX_ENABLE, ioaddr + EL3_CMD);
- netif_wake_queue(dev);
-}
-
-static netdev_tx_t el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct el3_private *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
- unsigned long flags;
-
- netif_stop_queue(dev);
-
- dev->stats.tx_bytes += skb->len;
-
- if (el3_debug > 4) {
- pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
- dev->name, skb->len, inw(ioaddr + EL3_STATUS));
- }
- /*
- * We lock the driver against other processors. Note
- * we don't need to lock versus the IRQ as we suspended
- * that. This means that we lose the ability to take
- * an RX during a TX upload. That sucks a bit with SMP
- * on an original 3c509 (2K buffer).
- *
- * Using disable_irq stops us crapping on other
- * time sensitive devices.
- */
-
- spin_lock_irqsave(&lp->lock, flags);
-
- /* Put out the doubleword header... */
- outw(skb->len, ioaddr + TX_FIFO);
- outw(0x00, ioaddr + TX_FIFO);
- /* ... and the packet rounded to a doubleword. */
- outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-
- if (inw(ioaddr + TX_FREE) > 1536) {
- netif_start_queue(dev);
- } else {
- /* Interrupt us when the FIFO has room for max-sized packet. */
- outw(SET_TX_THRESHOLD + 1536, ioaddr + EL3_CMD);
- }
-
- spin_unlock_irqrestore(&lp->lock, flags);
-
- dev_consume_skb_any(skb);
-
- /* Clear the Tx status stack. */
- {
- short tx_status;
- int i = 4;
-
- while (--i > 0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
- if (tx_status & 0x38)
- dev->stats.tx_aborted_errors++;
- if (tx_status & 0x30)
- outw(TX_RESET, ioaddr + EL3_CMD);
- if (tx_status & 0x3C)
- outw(TX_ENABLE, ioaddr + EL3_CMD);
- /* Pop the status stack. */
- outb(0x00, ioaddr + TX_STATUS);
- }
- }
- return NETDEV_TX_OK;
-}
-
-/* The EL3 interrupt handler. */
-static irqreturn_t el3_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- int i = max_interrupt_work;
- struct el3_private *lp;
- int ioaddr, status;
-
- lp = netdev_priv(dev);
- spin_lock(&lp->lock);
-
- ioaddr = dev->base_addr;
-
- if (el3_debug > 4) {
- status = inw(ioaddr + EL3_STATUS);
- pr_debug("%s: interrupt, status %4.4x.\n", dev->name, status);
- }
-
- while ((status = inw(ioaddr + EL3_STATUS)) &
- (INT_LATCH | RX_COMPLETE | STATS_FULL)) {
-
- if (status & RX_COMPLETE)
- el3_rx(dev);
-
- if (status & TX_AVAILABLE) {
- if (el3_debug > 5)
- pr_debug(" TX room bit was handled.\n");
- /* There's room in the FIFO for a full-sized packet. */
- outw(ACK_INTR | TX_AVAILABLE, ioaddr + EL3_CMD);
- netif_wake_queue(dev);
- }
- if (status &
- (ADAPTER_FAILURE | RX_EARLY | STATS_FULL | TX_COMPLETE)) {
- /* Handle all uncommon interrupts. */
- if (status & STATS_FULL) {
- /* Empty statistics. */
- update_stats(dev);
- }
- if (status & RX_EARLY) {
- /* Rx early is unused. */
- el3_rx(dev);
- outw(ACK_INTR | RX_EARLY, ioaddr + EL3_CMD);
- }
- if (status & TX_COMPLETE) {
- /* Really Tx error. */
- short tx_status;
- int i = 4;
-
- while (--i > 0 &&
- ((tx_status = inb(ioaddr + TX_STATUS))
- > 0)) {
- if (tx_status & 0x38)
- dev->stats.tx_aborted_errors++;
- if (tx_status & 0x30)
- outw(TX_RESET,
- ioaddr + EL3_CMD);
- if (tx_status & 0x3C)
- outw(TX_ENABLE,
- ioaddr + EL3_CMD);
- /* Pop the status stack. */
- outb(0x00, ioaddr + TX_STATUS);
- }
- }
- if (status & ADAPTER_FAILURE) {
- /* Adapter failure requires Rx reset
- * and reinit.
- */
- outw(RX_RESET, ioaddr + EL3_CMD);
- /* Set the Rx filter to the current state. */
- outw((SET_RX_FILTER | RX_STATION |
- RX_BROADCAST |
- (dev->flags & IFF_ALLMULTI ?
- RX_MULTICAST : 0) |
- (dev->flags & IFF_PROMISC ?
- RX_PROM : 0)),
- ioaddr + EL3_CMD);
- /* Re-enable the receiver. */
- outw(RX_ENABLE, ioaddr + EL3_CMD);
- outw(ACK_INTR | ADAPTER_FAILURE,
- ioaddr + EL3_CMD);
- }
- }
-
- if (--i < 0) {
- pr_err("%s: Infinite loop in interrupt, status %4.4x.\n",
- dev->name, status);
- /* Clear all interrupts. */
- outw(ACK_INTR | 0xFF, ioaddr + EL3_CMD);
- break;
- }
- /* Acknowledge the IRQ. */
- outw(ACK_INTR | INT_REQ | INT_LATCH, ioaddr + EL3_CMD);
- }
-
- if (el3_debug > 4) {
- pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name,
- inw(ioaddr + EL3_STATUS));
- }
- spin_unlock(&lp->lock);
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- */
-static void el3_poll_controller(struct net_device *dev)
-{
- disable_irq(dev->irq);
- el3_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-static struct net_device_stats *el3_get_stats(struct net_device *dev)
-{
- struct el3_private *lp = netdev_priv(dev);
- unsigned long flags;
-
- /* This is fast enough not to bother with disable IRQ stuff. */
- spin_lock_irqsave(&lp->lock, flags);
- update_stats(dev);
- spin_unlock_irqrestore(&lp->lock, flags);
- return &dev->stats;
-}
-
-/* Update statistics. We change to register window 6, so this should be run
- * single-threaded if the device is active. This is expected to be a rare
- * operation, and it's simpler for the rest of the driver to assume that
- * window 1 is always valid rather than use a special window-state variable.
- */
-static void update_stats(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
-
- if (el3_debug > 5)
- pr_debug(" Updating the statistics.\n");
- /* Turn off statistics updates while reading. */
- outw(STATS_DISABLE, ioaddr + EL3_CMD);
- /* Switch to the stats window, and read everything. */
- EL3WINDOW(6);
- dev->stats.tx_carrier_errors += inb(ioaddr + 0);
- dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
- /* Multiple collisions. */ inb(ioaddr + 2);
- dev->stats.collisions += inb(ioaddr + 3);
- dev->stats.tx_window_errors += inb(ioaddr + 4);
- dev->stats.rx_fifo_errors += inb(ioaddr + 5);
- dev->stats.tx_packets += inb(ioaddr + 6);
- /* Rx packets */ inb(ioaddr + 7);
- /* Tx deferrals */ inb(ioaddr + 8);
- inw(ioaddr + 10); /* Total Rx and Tx octets. */
- inw(ioaddr + 12);
-
- /* Back to window 1, and turn statistics back on. */
- EL3WINDOW(1);
- outw(STATS_ENABLE, ioaddr + EL3_CMD);
-}
-
-static int el3_rx(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
- short rx_status;
-
- if (el3_debug > 5)
- pr_debug(" In rx_packet(), status %4.4x, rx_status %4.4x.\n",
- inw(ioaddr + EL3_STATUS), inw(ioaddr + RX_STATUS));
- while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
- if (rx_status & 0x4000) {
- /* Error, update stats. */
- short error = rx_status & 0x3800;
-
- outw(RX_DISCARD, ioaddr + EL3_CMD);
- dev->stats.rx_errors++;
- switch (error) {
- case 0x0000:
- dev->stats.rx_over_errors++;
- break;
- case 0x0800:
- dev->stats.rx_length_errors++;
- break;
- case 0x1000:
- dev->stats.rx_frame_errors++;
- break;
- case 0x1800:
- dev->stats.rx_length_errors++;
- break;
- case 0x2000:
- dev->stats.rx_frame_errors++;
- break;
- case 0x2800:
- dev->stats.rx_crc_errors++; break;
- }
- } else {
- short pkt_len = rx_status & 0x7ff;
- struct sk_buff *skb;
-
- skb = netdev_alloc_skb(dev, pkt_len + 5);
- if (el3_debug > 4)
- pr_debug("Receiving packet size %d status %4.4x.\n",
- pkt_len, rx_status);
- if (skb) {
- /* Align IP on 16 byte. */
- skb_reserve(skb, 2);
-
- /* 'skb->data' points to the start of sk_buff
- * data area.
- */
- insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
- (pkt_len + 3) >> 2);
-
- /* Pop top Rx packet. */
- outw(RX_DISCARD, ioaddr + EL3_CMD);
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->stats.rx_bytes += pkt_len;
- dev->stats.rx_packets++;
- continue;
- }
- outw(RX_DISCARD, ioaddr + EL3_CMD);
- dev->stats.rx_dropped++;
- if (el3_debug)
- pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n",
- dev->name, pkt_len);
- }
- inw(ioaddr + EL3_STATUS); /* Delay. */
- while (inw(ioaddr + EL3_STATUS) & 0x1000)
- pr_debug(" Waiting for 3c509 to discard packet, status %x.\n",
- inw(ioaddr + EL3_STATUS));
- }
-
- return 0;
-}
-
-/* Set or clear the multicast filter for this adaptor. */
-static void set_multicast_list(struct net_device *dev)
-{
- struct el3_private *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
- int mc_count = netdev_mc_count(dev);
- unsigned long flags;
-
- if (el3_debug > 1) {
- static int old;
-
- if (old != mc_count) {
- old = mc_count;
- pr_debug("%s: Setting Rx mode to %d addresses.\n",
- dev->name, mc_count);
- }
- }
- spin_lock_irqsave(&lp->lock, flags);
- if (dev->flags & IFF_PROMISC) {
- outw((SET_RX_FILTER | RX_STATION | RX_MULTICAST |
- RX_BROADCAST | RX_PROM),
- ioaddr + EL3_CMD);
- } else if (mc_count || (dev->flags & IFF_ALLMULTI)) {
- outw(SET_RX_FILTER | RX_STATION | RX_MULTICAST | RX_BROADCAST,
- ioaddr + EL3_CMD);
- } else {
- outw(SET_RX_FILTER | RX_STATION | RX_BROADCAST,
- ioaddr + EL3_CMD);
- }
- spin_unlock_irqrestore(&lp->lock, flags);
-}
-
-static int el3_close(struct net_device *dev)
-{
- struct el3_private *lp = netdev_priv(dev);
- int ioaddr = dev->base_addr;
-
- if (el3_debug > 2)
- pr_debug("%s: Shutting down ethercard.\n", dev->name);
-
- el3_down(dev);
-
- free_irq(dev->irq, dev);
- /* Switching back to window 0 disables the IRQ. */
- EL3WINDOW(0);
- if (lp->type != EL3_EISA) {
- /* But we explicitly zero the IRQ line select anyway. Don't do
- * it on EISA cards, it prevents the module from getting an
- * IRQ after unload+reload...
- */
- outw(0x0f00, ioaddr + WN0_IRQ);
- }
-
- return 0;
-}
-
-static int el3_link_ok(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
- u16 tmp;
-
- EL3WINDOW(4);
- tmp = inw(ioaddr + WN4_MEDIA);
- EL3WINDOW(1);
- return tmp & (1 << 11);
-}
-
-static void el3_netdev_get_ecmd(struct net_device *dev,
- struct ethtool_link_ksettings *cmd)
-{
- int ioaddr = dev->base_addr;
- u32 supported;
- u16 tmp;
-
- EL3WINDOW(0);
- /* Obtain current transceiver via WN4_MEDIA? */
- tmp = inw(ioaddr + WN0_ADDR_CONF);
- switch (tmp >> 14) {
- case 0:
- cmd->base.port = PORT_TP;
- break;
- case 1:
- cmd->base.port = PORT_AUI;
- break;
- case 3:
- cmd->base.port = PORT_BNC;
- break;
- default:
- break;
- }
-
- cmd->base.duplex = DUPLEX_HALF;
- supported = 0;
- tmp = inw(ioaddr + WN0_CONF_CTRL);
- if (tmp & (1 << 13))
- supported |= SUPPORTED_AUI;
- if (tmp & (1 << 12))
- supported |= SUPPORTED_BNC;
- if (tmp & (1 << 9)) {
- supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full; /* hmm... */
- EL3WINDOW(4);
- tmp = inw(ioaddr + WN4_NETDIAG);
- if (tmp & FD_ENABLE)
- cmd->base.duplex = DUPLEX_FULL;
- }
-
- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
- supported);
- cmd->base.speed = SPEED_10;
- EL3WINDOW(1);
-}
-
-static int el3_netdev_set_ecmd(struct net_device *dev,
- const struct ethtool_link_ksettings *cmd)
-{
- int ioaddr = dev->base_addr;
- u16 tmp;
-
- if (cmd->base.speed != SPEED_10)
- return -EINVAL;
- if (cmd->base.duplex != DUPLEX_HALF && cmd->base.duplex != DUPLEX_FULL)
- return -EINVAL;
-
- /* change XCVR type */
- EL3WINDOW(0);
- tmp = inw(ioaddr + WN0_ADDR_CONF);
- switch (cmd->base.port) {
- case PORT_TP:
- tmp &= ~(3 << 14);
- dev->if_port = 0;
- break;
- case PORT_AUI:
- tmp &= ~(3 << 14);
- tmp |= 1 << 14;
- dev->if_port = 1;
- break;
- case PORT_BNC:
- tmp |= 3 << 14;
- dev->if_port = 3;
- break;
- default:
- return -EINVAL;
- }
-
- outw(tmp, ioaddr + WN0_ADDR_CONF);
- if (dev->if_port == 3) {
- /* Fire up the DC-DC converter if BNC gets enabled. */
- tmp = inw(ioaddr + WN0_ADDR_CONF);
- if (tmp & (3 << 14)) {
- outw(START_COAX, ioaddr + EL3_CMD);
- udelay(800);
- } else {
- return -EIO;
- }
- }
-
- EL3WINDOW(4);
- tmp = inw(ioaddr + WN4_NETDIAG);
- if (cmd->base.duplex == DUPLEX_FULL)
- tmp |= FD_ENABLE;
- else
- tmp &= ~FD_ENABLE;
- outw(tmp, ioaddr + WN4_NETDIAG);
- EL3WINDOW(1);
-
- return 0;
-}
-
-static void el3_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- strscpy(info->driver, DRV_NAME, sizeof(info->driver));
-}
-
-static int el3_get_link_ksettings(struct net_device *dev,
- struct ethtool_link_ksettings *cmd)
-{
- struct el3_private *lp = netdev_priv(dev);
-
- spin_lock_irq(&lp->lock);
- el3_netdev_get_ecmd(dev, cmd);
- spin_unlock_irq(&lp->lock);
- return 0;
-}
-
-static int el3_set_link_ksettings(struct net_device *dev,
- const struct ethtool_link_ksettings *cmd)
-{
- struct el3_private *lp = netdev_priv(dev);
- int ret;
-
- spin_lock_irq(&lp->lock);
- ret = el3_netdev_set_ecmd(dev, cmd);
- spin_unlock_irq(&lp->lock);
- return ret;
-}
-
-static u32 el3_get_link(struct net_device *dev)
-{
- struct el3_private *lp = netdev_priv(dev);
- u32 ret;
-
- spin_lock_irq(&lp->lock);
- ret = el3_link_ok(dev);
- spin_unlock_irq(&lp->lock);
- return ret;
-}
-
-static u32 el3_get_msglevel(struct net_device *dev)
-{
- return el3_debug;
-}
-
-static void el3_set_msglevel(struct net_device *dev, u32 v)
-{
- el3_debug = v;
-}
-
-static const struct ethtool_ops ethtool_ops = {
- .get_drvinfo = el3_get_drvinfo,
- .get_link = el3_get_link,
- .get_msglevel = el3_get_msglevel,
- .set_msglevel = el3_set_msglevel,
- .get_link_ksettings = el3_get_link_ksettings,
- .set_link_ksettings = el3_set_link_ksettings,
-};
-
-static void el3_down(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
-
- netif_stop_queue(dev);
-
- /* Turn off statistics ASAP. We update lp->stats below. */
- outw(STATS_DISABLE, ioaddr + EL3_CMD);
-
- /* Disable the receiver and transmitter. */
- outw(RX_DISABLE, ioaddr + EL3_CMD);
- outw(TX_DISABLE, ioaddr + EL3_CMD);
-
- if (dev->if_port == 3) {
- /* Turn off thinnet power. Green! */
- outw(STOP_COAX, ioaddr + EL3_CMD);
- } else if (dev->if_port == 0) {
- /* Disable link beat and jabber, if_port may change here next
- * open().
- */
- EL3WINDOW(4);
- outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
- }
-
- outw(SET_INTR_ENB | 0x0000, ioaddr + EL3_CMD);
-
- update_stats(dev);
-}
-
-static void el3_up(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
- int i, sw_info, net_diag;
-
- /* Activating the board required and does no harm otherwise. */
- outw(0x0001, ioaddr + 4);
-
- /* Set the IRQ line. */
- outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
-
- /* Set the station address in window 2 each time opened. */
- EL3WINDOW(2);
-
- for (i = 0; i < 6; i++)
- outb(dev->dev_addr[i], ioaddr + i);
-
- if ((dev->if_port & 0x03) == 3) {
- /* BNC interface */
-
- /* Start the thinnet transceiver. We should really wait
- * 50ms...
- */
- outw(START_COAX, ioaddr + EL3_CMD);
- } else if ((dev->if_port & 0x03) == 0) {
- /* 10baseT interface */
-
- /* Combine secondary sw_info word (the adapter level) and
- * primary sw_info word (duplex setting plus other useless
- * bits).
- */
- EL3WINDOW(0);
- sw_info = (read_eeprom(ioaddr, 0x14) & 0x400f) |
- (read_eeprom(ioaddr, 0x0d) & 0xBff0);
-
- EL3WINDOW(4);
- net_diag = inw(ioaddr + WN4_NETDIAG);
- /* Temporarily assume full-duplex will be set. */
- net_diag = (net_diag | FD_ENABLE);
- pr_info("%s: ", dev->name);
- switch (dev->if_port & 0x0c) {
- case 12:
- /* Force full-duplex mode if 3c5x9b. */
- if (sw_info & 0x000f) {
- pr_cont("Forcing 3c5x9b full-duplex mode");
- break;
- }
- fallthrough;
- case 8:
- /* Set full-duplex mode based on eeprom config
- * setting.
- */
- if ((sw_info & 0x000f) && (sw_info & 0x8000)) {
- pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
- break;
- }
- fallthrough;
- default:
- /* xcvr = (0 || 4) OR user has an old 3c5x9 non "B"
- * model.
- */
- pr_cont("Setting 3c5x9/3c5x9B half-duplex mode");
- /* Disable full duplex. */
- net_diag = (net_diag & ~FD_ENABLE);
- }
-
- outw(net_diag, ioaddr + WN4_NETDIAG);
- pr_cont(" if_port: %d, sw_info: %4.4x\n",
- dev->if_port, sw_info);
- if (el3_debug > 3)
- pr_debug("%s: 3c5x9 net diag word is now: %4.4x.\n",
- dev->name, net_diag);
- /* Enable link beat and jabber check. */
- outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
- }
-
- /* Switch to the stats window, and clear all stats by reading. */
- outw(STATS_DISABLE, ioaddr + EL3_CMD);
- EL3WINDOW(6);
- for (i = 0; i < 9; i++)
- inb(ioaddr + i);
- inw(ioaddr + 10);
- inw(ioaddr + 12);
-
- /* Switch to register set 1 for normal use. */
- EL3WINDOW(1);
-
- /* Accept b-case and phys addr only. */
- outw(SET_RX_FILTER | RX_STATION | RX_BROADCAST, ioaddr + EL3_CMD);
- /* Turn on statistics. */
- outw(STATS_ENABLE, ioaddr + EL3_CMD);
-
- /* Enable the receiver. */
- outw(RX_ENABLE, ioaddr + EL3_CMD);
- /* Enable transmitter. */
- outw(TX_ENABLE, ioaddr + EL3_CMD);
- /* Allow status bits to be seen. */
- outw(SET_STATUS_ENB | 0xff, ioaddr + EL3_CMD);
- /* Ack all pending events, and set active indicator mask. */
- outw(ACK_INTR | INT_LATCH | TX_AVAILABLE | RX_EARLY | INT_REQ,
- ioaddr + EL3_CMD);
- outw((SET_INTR_ENB | INT_LATCH | TX_AVAILABLE | TX_COMPLETE |
- RX_COMPLETE | STATS_FULL),
- ioaddr + EL3_CMD);
-
- netif_start_queue(dev);
-}
-
-/* Power Management support functions */
-#ifdef CONFIG_PM
-
-static int el3_suspend(struct device *pdev, pm_message_t state)
-{
- struct net_device *dev;
- struct el3_private *lp;
- unsigned long flags;
- int ioaddr;
-
- dev = dev_get_drvdata(pdev);
- lp = netdev_priv(dev);
- ioaddr = dev->base_addr;
-
- spin_lock_irqsave(&lp->lock, flags);
-
- if (netif_running(dev))
- netif_device_detach(dev);
-
- el3_down(dev);
- outw(POWER_DOWN, ioaddr + EL3_CMD);
-
- spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
-}
-
-static int el3_resume(struct device *pdev)
-{
- struct net_device *dev;
- struct el3_private *lp;
- unsigned long flags;
- int ioaddr;
-
- dev = dev_get_drvdata(pdev);
- lp = netdev_priv(dev);
- ioaddr = dev->base_addr;
-
- spin_lock_irqsave(&lp->lock, flags);
-
- outw(POWER_UP, ioaddr + EL3_CMD);
- EL3WINDOW(0);
- el3_up(dev);
-
- if (netif_running(dev))
- netif_device_attach(dev);
-
- spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
-}
-
-#endif /* CONFIG_PM */
-
-module_param(debug, int, 0);
-module_param_hw_array(irq, int, irq, NULL, 0);
-module_param(max_interrupt_work, int, 0);
-MODULE_PARM_DESC(debug, "debug level (0-6)");
-MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
-MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-#ifdef CONFIG_PNP
-module_param(nopnp, int, 0);
-MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
-#endif /* CONFIG_PNP */
-MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
-MODULE_LICENSE("GPL");
-
-static int __init el3_init_module(void)
-{
- int ret = 0;
-
- if (debug >= 0)
- el3_debug = debug;
-
-#ifdef CONFIG_PNP
- if (!nopnp) {
- ret = pnp_register_driver(&el3_pnp_driver);
- if (!ret)
- pnp_registered = 1;
- }
-#endif
- /* Select an open I/O location at 0x1*0 to do ISA contention select. */
- /* Start with 0x110 to avoid some sound cards.*/
- for (id_port = 0x110; id_port < 0x200; id_port += 0x10) {
- if (!request_region(id_port, 1, "3c509-control"))
- continue;
- outb(0x00, id_port);
- outb(0xff, id_port);
- if (inb(id_port) & 0x01)
- break;
- release_region(id_port, 1);
- }
- if (id_port >= 0x200) {
- id_port = 0;
- pr_err("No I/O port available for 3c509 activation.\n");
- } else {
- ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
- if (!ret)
- isa_registered = 1;
- }
-#ifdef CONFIG_EISA
- ret = eisa_driver_register(&el3_eisa_driver);
- if (!ret)
- eisa_registered = 1;
-#endif
-
-#ifdef CONFIG_PNP
- if (pnp_registered)
- ret = 0;
-#endif
- if (isa_registered)
- ret = 0;
-#ifdef CONFIG_EISA
- if (eisa_registered)
- ret = 0;
-#endif
- return ret;
-}
-
-static void __exit el3_cleanup_module(void)
-{
-#ifdef CONFIG_PNP
- if (pnp_registered)
- pnp_unregister_driver(&el3_pnp_driver);
-#endif
- if (isa_registered)
- isa_unregister_driver(&el3_isa_driver);
- if (id_port)
- release_region(id_port, 1);
-#ifdef CONFIG_EISA
- if (eisa_registered)
- eisa_driver_unregister(&el3_eisa_driver);
-#endif
-}
-
-module_init(el3_init_module);
-module_exit(el3_cleanup_module);
diff --git a/drivers/net/ethernet/3com/Makefile b/drivers/net/ethernet/3com/Makefile
index 2c65e4721..5c4d07f1d 100644
--- a/drivers/net/ethernet/3com/Makefile
+++ b/drivers/net/ethernet/3com/Makefile
@@ -3,6 +3,5 @@
# Makefile for the 3Com Ethernet device drivers
#
-obj-$(CONFIG_EL3) += 3c509.o
obj-$(CONFIG_VORTEX) += 3c59x.o
obj-$(CONFIG_TYPHOON) += typhoon.o
diff --git a/drivers/net/ethernet/3com/Makefile.save b/drivers/net/ethernet/3com/Makefile.save
new file mode 100644
index 000000000..5c4d07f1d
--- /dev/null
+++ b/drivers/net/ethernet/3com/Makefile.save
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the 3Com Ethernet device drivers
+#
+
+obj-$(CONFIG_VORTEX) += 3c59x.o
+obj-$(CONFIG_TYPHOON) += typhoon.o
diff --git a/drivers/net/ethernet/8390/Makefile b/drivers/net/ethernet/8390/Makefile
index bca5babda..0e199848f 100644
--- a/drivers/net/ethernet/8390/Makefile
+++ b/drivers/net/ethernet/8390/Makefile
@@ -3,15 +3,15 @@
# Makefile for the 8390 network device drivers.
#
-obj-$(CONFIG_MAC8390) += mac8390.o
-obj-$(CONFIG_APNE) += apne.o 8390.o
+# obj-$(CONFIG_MAC8390) += mac8390.o
+# obj-$(CONFIG_APNE) += apne.o 8390.o
obj-$(CONFIG_ARM_ETHERH) += etherh.o
-obj-$(CONFIG_AX88796) += ax88796.o
-obj-$(CONFIG_HYDRA) += hydra.o
+# obj-$(CONFIG_AX88796) += ax88796.o
+# obj-$(CONFIG_HYDRA) += hydra.o
obj-$(CONFIG_MCF8390) += mcf8390.o
-obj-$(CONFIG_NE2000) += ne.o 8390p.o
+# obj-$(CONFIG_NE2000) += ne.o 8390p.o
obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
-obj-$(CONFIG_STNIC) += stnic.o 8390.o
+# obj-$(CONFIG_STNIC) += stnic.o 8390.o
obj-$(CONFIG_XSURF100) += xsurf100.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o
+# obj-$(CONFIG_ZORRO8390) += zorro8390.o
diff --git a/drivers/net/ethernet/8390/apne.c b/drivers/net/ethernet/8390/apne.c
deleted file mode 100644
index 828edca8d..000000000
--- a/drivers/net/ethernet/8390/apne.c
+++ /dev/null
@@ -1,614 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
- *
- * (C) Copyright 1997 Alain Malek
- * (Alain.Malek@cryogen.com)
- *
- * ----------------------------------------------------------------------------
- *
- * This program is based on
- *
- * ne.c: A general non-shared-memory NS8390 ethernet driver for linux
- * Written 1992-94 by Donald Becker.
- *
- * 8390.c: A general NS8390 ethernet driver core for linux.
- * Written 1992-94 by Donald Becker.
- *
- * cnetdevice: A Sana-II ethernet driver for AmigaOS
- * Written by Bruce Abbott (bhabbott@inhb.co.nz)
- *
- * ----------------------------------------------------------------------------
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/amigayle.h>
-#include <asm/amipcmcia.h>
-
-#include "8390.h"
-
-/* ---- No user-serviceable parts below ---- */
-
-#define DRV_NAME "apne"
-
-#define NE_BASE (dev->base_addr)
-#define NE_CMD 0x00
-#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
-#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT 0x20
-
-#define NE_EN0_ISR 0x07
-#define NE_EN0_DCFG 0x0e
-
-#define NE_EN0_RSARLO 0x08
-#define NE_EN0_RSARHI 0x09
-#define NE_EN0_RCNTLO 0x0a
-#define NE_EN0_RXCR 0x0c
-#define NE_EN0_TXCR 0x0d
-#define NE_EN0_RCNTHI 0x0b
-#define NE_EN0_IMR 0x0f
-
-#define NE1SM_START_PG 0x20 /* First page of TX buffer */
-#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
-#define NESM_START_PG 0x40 /* First page of TX buffer */
-#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-
-static int apne_probe1(struct net_device *dev, int ioaddr);
-
-static void apne_reset_8390(struct net_device *dev);
-static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
- int ring_page);
-static void apne_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void apne_block_output(struct net_device *dev, const int count,
- const unsigned char *buf, const int start_page);
-static irqreturn_t apne_interrupt(int irq, void *dev_id);
-
-static int init_pcmcia(void);
-
-/* IO base address used for nic */
-
-#define IOBASE 0x300
-
-/*
- use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand
- you can find the values to use by looking at the cnet.device
- config file example (the default values are for the CNET40BC card)
-*/
-
-/*
-#define MANUAL_CONFIG 0x20
-#define MANUAL_OFFSET 0x3f8
-
-#define MANUAL_HWADDR0 0x00
-#define MANUAL_HWADDR1 0x12
-#define MANUAL_HWADDR2 0x34
-#define MANUAL_HWADDR3 0x56
-#define MANUAL_HWADDR4 0x78
-#define MANUAL_HWADDR5 0x9a
-*/
-
-static const char version[] =
- "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
-
-static int apne_owned; /* signal if card already owned */
-
-static u32 apne_msg_enable;
-module_param_named(msg_enable, apne_msg_enable, uint, 0444);
-MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
-
-static struct net_device * __init apne_probe(void)
-{
- struct net_device *dev;
- struct ei_device *ei_local;
-
-#ifndef MANUAL_CONFIG
- char tuple[8];
-#endif
- int err;
-
- if (!MACH_IS_AMIGA)
- return ERR_PTR(-ENODEV);
-
- if (apne_owned)
- return ERR_PTR(-ENODEV);
-
- if ( !(AMIGAHW_PRESENT(PCMCIA)) )
- return ERR_PTR(-ENODEV);
-
- pr_info("Looking for PCMCIA ethernet card : ");
-
- /* check if a card is inserted */
- if (!(PCMCIA_INSERTED)) {
- pr_cont("NO PCMCIA card inserted\n");
- return ERR_PTR(-ENODEV);
- }
-
- dev = alloc_ei_netdev();
- if (!dev)
- return ERR_PTR(-ENOMEM);
- ei_local = netdev_priv(dev);
- ei_local->msg_enable = apne_msg_enable;
-
- /* disable pcmcia irq for readtuple */
- pcmcia_disable_irq();
-
-#ifndef MANUAL_CONFIG
- if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
- (tuple[2] != CISTPL_FUNCID_NETWORK)) {
- pr_cont("not an ethernet card\n");
- /* XXX: shouldn't we re-enable irq here? */
- free_netdev(dev);
- return ERR_PTR(-ENODEV);
- }
-#endif
-
- pr_cont("ethernet PCMCIA card inserted\n");
-
- if (!init_pcmcia()) {
- /* XXX: shouldn't we re-enable irq here? */
- free_netdev(dev);
- return ERR_PTR(-ENODEV);
- }
-
- if (!request_region(IOBASE, 0x20, DRV_NAME)) {
- free_netdev(dev);
- return ERR_PTR(-EBUSY);
- }
-
- err = apne_probe1(dev, IOBASE);
- if (err) {
- release_region(IOBASE, 0x20);
- free_netdev(dev);
- return ERR_PTR(err);
- }
- err = register_netdev(dev);
- if (!err)
- return dev;
-
- pcmcia_disable_irq();
- free_irq(IRQ_AMIGA_PORTS, dev);
- pcmcia_reset();
- release_region(IOBASE, 0x20);
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
-static int __init apne_probe1(struct net_device *dev, int ioaddr)
-{
- int i;
- unsigned char SA_prom[32];
- int wordlength = 2;
- const char *name = NULL;
- int start_page, stop_page;
-#ifndef MANUAL_HWADDR0
- int neX000, ctron;
-#endif
- static unsigned version_printed;
-
- if ((apne_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
- netdev_info(dev, version);
-
- netdev_info(dev, "PCMCIA NE*000 ethercard probe");
-
- /* Reset card. Who knows what dain-bramaged state it was left in. */
- { unsigned long reset_start_time = jiffies;
-
- outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
- while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- pr_cont(" not found (no reset ack).\n");
- return -ENODEV;
- }
-
- outb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */
- }
-
-#ifndef MANUAL_HWADDR0
-
- /* Read the 16 bytes of station address PROM.
- We must first initialize registers, similar to NS8390_init(eifdev, 0).
- We can't reliably read the SAPROM address without this.
- (I learned the hard way!). */
- {
- struct {unsigned long value, offset; } program_seq[] = {
- {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
- {0x48, NE_EN0_DCFG}, /* Set byte-wide (0x48) access. */
- {0x00, NE_EN0_RCNTLO}, /* Clear the count regs. */
- {0x00, NE_EN0_RCNTHI},
- {0x00, NE_EN0_IMR}, /* Mask completion irq. */
- {0xFF, NE_EN0_ISR},
- {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode. */
- {32, NE_EN0_RCNTLO},
- {0x00, NE_EN0_RCNTHI},
- {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000. */
- {0x00, NE_EN0_RSARHI},
- {E8390_RREAD+E8390_START, NE_CMD},
- };
- for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
- outb(program_seq[i].value, ioaddr + program_seq[i].offset);
- }
-
- }
- for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
- SA_prom[i] = inb(ioaddr + NE_DATAPORT);
- SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
- if (SA_prom[i] != SA_prom[i+1])
- wordlength = 1;
- }
-
- /* At this point, wordlength *only* tells us if the SA_prom is doubled
- up or not because some broken PCI cards don't respect the byte-wide
- request in program_seq above, and hence don't have doubled up values.
- These broken cards would otherwise be detected as an ne1000. */
-
- if (wordlength == 2)
- for (i = 0; i < 16; i++)
- SA_prom[i] = SA_prom[i+i];
-
- if (wordlength == 2) {
- /* We must set the 8390 for word mode. */
- outb(0x49, ioaddr + NE_EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
- } else {
- start_page = NE1SM_START_PG;
- stop_page = NE1SM_STOP_PG;
- }
-
- neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
- ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
-
- /* Set up the rest of the parameters. */
- if (neX000) {
- name = (wordlength == 2) ? "NE2000" : "NE1000";
- } else if (ctron) {
- name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
- start_page = 0x01;
- stop_page = (wordlength == 2) ? 0x40 : 0x20;
- } else {
- pr_cont(" not found.\n");
- return -ENXIO;
-
- }
-
-#else
- wordlength = 2;
- /* We must set the 8390 for word mode. */
- outb(0x49, ioaddr + NE_EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
-
- SA_prom[0] = MANUAL_HWADDR0;
- SA_prom[1] = MANUAL_HWADDR1;
- SA_prom[2] = MANUAL_HWADDR2;
- SA_prom[3] = MANUAL_HWADDR3;
- SA_prom[4] = MANUAL_HWADDR4;
- SA_prom[5] = MANUAL_HWADDR5;
- name = "NE2000";
-#endif
-
- dev->base_addr = ioaddr;
- dev->irq = IRQ_AMIGA_PORTS;
- dev->netdev_ops = &ei_netdev_ops;
-
- /* Install the Interrupt handler */
- i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
- if (i) return i;
-
- eth_hw_addr_set(dev, SA_prom);
-
- pr_cont(" %pM\n", dev->dev_addr);
-
- netdev_info(dev, "%s found.\n", name);
-
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
- ei_status.word16 = (wordlength == 2);
-
- ei_status.rx_start_page = start_page + TX_PAGES;
-
- ei_status.reset_8390 = &apne_reset_8390;
- ei_status.block_input = &apne_block_input;
- ei_status.block_output = &apne_block_output;
- ei_status.get_8390_hdr = &apne_get_8390_hdr;
-
- NS8390_init(dev, 0);
-
- pcmcia_ack_int(pcmcia_get_intreq()); /* ack PCMCIA int req */
- pcmcia_enable_irq();
-
- apne_owned = 1;
-
- return 0;
-}
-
-/* Hard reset the card. This used to pause for the same period that a
- 8390 reset command required, but that shouldn't be necessary. */
-static void
-apne_reset_8390(struct net_device *dev)
-{
- unsigned long reset_start_time = jiffies;
- struct ei_device *ei_local = netdev_priv(dev);
-
- init_pcmcia();
-
- netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
-
- outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
- ei_status.txing = 0;
- ei_status.dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- netdev_err(dev, "ne_reset_8390() did not complete.\n");
- break;
- }
- outb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- we don't need to be concerned with ring wrap as the header will be at
- the start of a page, so we optimize accordingly. */
-
-static void
-apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-
- int nic_base = dev->base_addr;
- int cnt;
- char *ptrc;
- short *ptrs;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- netdev_err(dev, "DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d][intr:%d].\n",
- ei_status.dmaing, ei_status.irqlock, dev->irq);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb(ENISR_RDC, nic_base + NE_EN0_ISR);
- outb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
- outb(0, nic_base + NE_EN0_RCNTHI);
- outb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */
- outb(ring_page, nic_base + NE_EN0_RSARHI);
- outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- if (ei_status.word16) {
- ptrs = (short*)hdr;
- for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
- *ptrs++ = inw(NE_BASE + NE_DATAPORT);
- } else {
- ptrc = (char*)hdr;
- for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++)
- *ptrc++ = inb(NE_BASE + NE_DATAPORT);
- }
-
- outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-
- le16_to_cpus(&hdr->count);
-}
-
-/* Block input and output, similar to the Crynwr packet driver. If you
- are porting to a new ethercard, look at the packet driver source for hints.
- The NEx000 doesn't share the on-board packet memory -- you have to put
- the packet out through the "remote DMA" dataport using outb. */
-
-static void
-apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
- int nic_base = dev->base_addr;
- char *buf = skb->data;
- char *ptrc;
- short *ptrs;
- int cnt;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- netdev_err(dev, "DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d][intr:%d].\n",
- ei_status.dmaing, ei_status.irqlock, dev->irq);
- return;
- }
- ei_status.dmaing |= 0x01;
- outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb(ENISR_RDC, nic_base + NE_EN0_ISR);
- outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
- outb(count >> 8, nic_base + NE_EN0_RCNTHI);
- outb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
- outb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
- outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16) {
- ptrs = (short*)buf;
- for (cnt = 0; cnt < (count>>1); cnt++)
- *ptrs++ = inw(NE_BASE + NE_DATAPORT);
- if (count & 0x01) {
- buf[count-1] = inb(NE_BASE + NE_DATAPORT);
- }
- } else {
- ptrc = buf;
- for (cnt = 0; cnt < count; cnt++)
- *ptrc++ = inb(NE_BASE + NE_DATAPORT);
- }
-
- outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-static void
-apne_block_output(struct net_device *dev, int count,
- const unsigned char *buf, const int start_page)
-{
- int nic_base = NE_BASE;
- unsigned long dma_start;
- char *ptrc;
- short *ptrs;
- int cnt;
-
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
- if (ei_status.word16 && (count & 0x01))
- count++;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- netdev_err(dev, "DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d][intr:%d]\n",
- ei_status.dmaing, ei_status.irqlock, dev->irq);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
- outb(ENISR_RDC, nic_base + NE_EN0_ISR);
-
- /* Now the normal output. */
- outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
- outb(count >> 8, nic_base + NE_EN0_RCNTHI);
- outb(0x00, nic_base + NE_EN0_RSARLO);
- outb(start_page, nic_base + NE_EN0_RSARHI);
-
- outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16) {
- ptrs = (short*)buf;
- for (cnt = 0; cnt < count>>1; cnt++)
- outw(*ptrs++, NE_BASE+NE_DATAPORT);
- } else {
- ptrc = (char*)buf;
- for (cnt = 0; cnt < count; cnt++)
- outb(*ptrc++, NE_BASE + NE_DATAPORT);
- }
-
- dma_start = jiffies;
-
- while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
- netdev_warn(dev, "timeout waiting for Tx RDC.\n");
- apne_reset_8390(dev);
- NS8390_init(dev,1);
- break;
- }
-
- outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-static irqreturn_t apne_interrupt(int irq, void *dev_id)
-{
- unsigned char pcmcia_intreq;
-
- if (!(gayle.inten & GAYLE_IRQ_IRQ))
- return IRQ_NONE;
-
- pcmcia_intreq = pcmcia_get_intreq();
-
- if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) {
- pcmcia_ack_int(pcmcia_intreq);
- return IRQ_NONE;
- }
- if (apne_msg_enable & NETIF_MSG_INTR)
- pr_debug("pcmcia intreq = %x\n", pcmcia_intreq);
- pcmcia_disable_irq(); /* to get rid of the sti() within ei_interrupt */
- ei_interrupt(irq, dev_id);
- pcmcia_ack_int(pcmcia_get_intreq());
- pcmcia_enable_irq();
- return IRQ_HANDLED;
-}
-
-static struct net_device *apne_dev;
-
-static int __init apne_module_init(void)
-{
- apne_dev = apne_probe();
- return PTR_ERR_OR_ZERO(apne_dev);
-}
-
-static void __exit apne_module_exit(void)
-{
- unregister_netdev(apne_dev);
-
- pcmcia_disable_irq();
-
- free_irq(IRQ_AMIGA_PORTS, apne_dev);
-
- pcmcia_reset();
-
- release_region(IOBASE, 0x20);
-
- free_netdev(apne_dev);
-}
-module_init(apne_module_init);
-module_exit(apne_module_exit);
-
-static int init_pcmcia(void)
-{
- u_char config;
-#ifndef MANUAL_CONFIG
- u_char tuple[32];
- int offset_len;
-#endif
- u_long offset;
-
- pcmcia_reset();
- pcmcia_program_voltage(PCMCIA_0V);
- pcmcia_access_speed(PCMCIA_SPEED_250NS);
- pcmcia_write_enable();
-
-#ifdef MANUAL_CONFIG
- config = MANUAL_CONFIG;
-#else
- /* get and write config byte to enable IO port */
-
- if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3)
- return 0;
-
- config = tuple[2] & 0x3f;
-#endif
-#ifdef MANUAL_OFFSET
- offset = MANUAL_OFFSET;
-#else
- if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6)
- return 0;
-
- offset_len = (tuple[2] & 0x3) + 1;
- offset = 0;
- while(offset_len--) {
- offset = (offset << 8) | tuple[4+offset_len];
- }
-#endif
-
- out_8(GAYLE_ATTRIBUTE+offset, config);
-
- return 1;
-}
-
-MODULE_DESCRIPTION("National Semiconductor 8390 Amiga PCMCIA ethernet driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
deleted file mode 100644
index e1695d0fb..000000000
--- a/drivers/net/ethernet/8390/ax88796.c
+++ /dev/null
@@ -1,1022 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* drivers/net/ethernet/8390/ax88796.c
- *
- * Copyright 2005,2007 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * Asix AX88796 10/100 Ethernet controller support
- * Based on ne.c, by Donald Becker, et-al.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/isapnp.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/mdio-bitbang.h>
-#include <linux/phy.h>
-#include <linux/eeprom_93cx6.h>
-#include <linux/slab.h>
-
-#include <net/ax88796.h>
-
-
-/* Rename the lib8390.c functions to show that they are in this driver */
-#define __ei_open ax_ei_open
-#define __ei_close ax_ei_close
-#define __ei_poll ax_ei_poll
-#define __ei_start_xmit ax_ei_start_xmit
-#define __ei_tx_timeout ax_ei_tx_timeout
-#define __ei_get_stats ax_ei_get_stats
-#define __ei_set_multicast_list ax_ei_set_multicast_list
-#define __ei_interrupt ax_ei_interrupt
-#define ____alloc_ei_netdev ax__alloc_ei_netdev
-#define __NS8390_init ax_NS8390_init
-
-/* force unsigned long back to 'void __iomem *' */
-#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
-
-#define ei_inb(_a) readb(ax_convert_addr(_a))
-#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
-
-#define ei_inb_p(_a) ei_inb(_a)
-#define ei_outb_p(_v, _a) ei_outb(_v, _a)
-
-/* define EI_SHIFT() to take into account our register offsets */
-#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
-
-/* Ensure we have our RCR base value */
-#define AX88796_PLATFORM
-
-static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
-
-#include "lib8390.c"
-
-#define DRV_NAME "ax88796"
-#define DRV_VERSION "1.00"
-
-/* from ne.c */
-#define NE_CMD EI_SHIFT(0x00)
-#define NE_RESET EI_SHIFT(0x1f)
-#define NE_DATAPORT EI_SHIFT(0x10)
-
-#define NE1SM_START_PG 0x20 /* First page of TX buffer */
-#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
-#define NESM_START_PG 0x40 /* First page of TX buffer */
-#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-#define AX_GPOC_PPDSET BIT(6)
-
-/* device private data */
-
-struct ax_device {
- struct mii_bus *mii_bus;
- struct mdiobb_ctrl bb_ctrl;
- void __iomem *addr_memr;
- u8 reg_memr;
- int link;
- int speed;
- int duplex;
-
- void __iomem *map2;
- const struct ax_plat_data *plat;
-
- unsigned char running;
- unsigned char resume_open;
- unsigned int irqflags;
-
- u32 reg_offsets[0x20];
-};
-
-static inline struct ax_device *to_ax_dev(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- return (struct ax_device *)(ei_local + 1);
-}
-
-void ax_NS8390_reinit(struct net_device *dev)
-{
- ax_NS8390_init(dev, 1);
-}
-
-EXPORT_SYMBOL_GPL(ax_NS8390_reinit);
-
-/*
- * ax_initial_check
- *
- * do an initial probe for the card to check whether it exists
- * and is functional
- */
-static int ax_initial_check(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *ioaddr = ei_local->mem;
- int reg0;
- int regd;
-
- reg0 = ei_inb(ioaddr);
- if (reg0 == 0xFF)
- return -ENODEV;
-
- ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
- regd = ei_inb(ioaddr + 0x0d);
- ei_outb(0xff, ioaddr + 0x0d);
- ei_outb(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
- ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
- if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
- ei_outb(reg0, ioaddr);
- ei_outb(regd, ioaddr + 0x0d); /* Restore the old values. */
- return -ENODEV;
- }
-
- return 0;
-}
-
-/*
- * Hard reset the card. This used to pause for the same period that a
- * 8390 reset command required, but that shouldn't be necessary.
- */
-static void ax_reset_8390(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned long reset_start_time = jiffies;
- void __iomem *addr = (void __iomem *)dev->base_addr;
-
- netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
-
- ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
-
- ei_local->txing = 0;
- ei_local->dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
- if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
- netdev_warn(dev, "%s: did not complete.\n", __func__);
- break;
- }
- }
-
- ei_outb(ENISR_RESET, addr + EN0_ISR); /* Ack intr. */
-}
-
-/* Wrapper for __ei_interrupt for platforms that have a platform-specific
- * way to find out whether the interrupt request might be caused by
- * the ax88796 chip.
- */
-static irqreturn_t ax_ei_interrupt_filtered(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct ax_device *ax = to_ax_dev(dev);
- struct platform_device *pdev = to_platform_device(dev->dev.parent);
-
- if (!ax->plat->check_irq(pdev))
- return IRQ_NONE;
-
- return ax_ei_interrupt(irq, dev_id);
-}
-
-static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
- int ring_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *nic_base = ei_local->mem;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_local->dmaing) {
- netdev_err(dev, "DMAing conflict in %s "
- "[DMAstat:%d][irqlock:%d].\n",
- __func__,
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing |= 0x01;
- ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
- ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
- ei_outb(0, nic_base + EN0_RCNTHI);
- ei_outb(0, nic_base + EN0_RSARLO); /* On page boundary */
- ei_outb(ring_page, nic_base + EN0_RSARHI);
- ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- if (ei_local->word16)
- ioread16_rep(nic_base + NE_DATAPORT, hdr,
- sizeof(struct e8390_pkt_hdr) >> 1);
- else
- ioread8_rep(nic_base + NE_DATAPORT, hdr,
- sizeof(struct e8390_pkt_hdr));
-
- ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_local->dmaing &= ~0x01;
-
- le16_to_cpus(&hdr->count);
-}
-
-
-/*
- * Block input and output, similar to the Crynwr packet driver. If
- * you are porting to a new ethercard, look at the packet driver
- * source for hints. The NEx000 doesn't share the on-board packet
- * memory -- you have to put the packet out through the "remote DMA"
- * dataport using ei_outb.
- */
-static void ax_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *nic_base = ei_local->mem;
- char *buf = skb->data;
-
- if (ei_local->dmaing) {
- netdev_err(dev,
- "DMAing conflict in %s "
- "[DMAstat:%d][irqlock:%d].\n",
- __func__,
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing |= 0x01;
-
- ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + NE_CMD);
- ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
- ei_outb(count >> 8, nic_base + EN0_RCNTHI);
- ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
- ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
- ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- if (ei_local->word16) {
- ioread16_rep(nic_base + NE_DATAPORT, buf, count >> 1);
- if (count & 0x01)
- buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
-
- } else {
- ioread8_rep(nic_base + NE_DATAPORT, buf, count);
- }
-
- ei_local->dmaing &= ~1;
-}
-
-static void ax_block_output(struct net_device *dev, int count,
- const unsigned char *buf, const int start_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *nic_base = ei_local->mem;
- unsigned long dma_start;
-
- /*
- * Round the count up for word writes. Do we need to do this?
- * What effect will an odd byte count have on the 8390? I
- * should check someday.
- */
- if (ei_local->word16 && (count & 0x01))
- count++;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_local->dmaing) {
- netdev_err(dev, "DMAing conflict in %s."
- "[DMAstat:%d][irqlock:%d]\n",
- __func__,
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
- ei_outb(ENISR_RDC, nic_base + EN0_ISR);
-
- /* Now the normal output. */
- ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
- ei_outb(count >> 8, nic_base + EN0_RCNTHI);
- ei_outb(0x00, nic_base + EN0_RSARLO);
- ei_outb(start_page, nic_base + EN0_RSARHI);
-
- ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
- if (ei_local->word16)
- iowrite16_rep(nic_base + NE_DATAPORT, buf, count >> 1);
- else
- iowrite8_rep(nic_base + NE_DATAPORT, buf, count);
-
- dma_start = jiffies;
-
- while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
- if (time_after(jiffies, dma_start + 2 * HZ / 100)) { /* 20ms */
- netdev_warn(dev, "timeout waiting for Tx RDC.\n");
- ax_reset_8390(dev);
- ax_NS8390_init(dev, 1);
- break;
- }
- }
-
- ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_local->dmaing &= ~0x01;
-}
-
-/* definitions for accessing MII/EEPROM interface */
-
-#define AX_MEMR EI_SHIFT(0x14)
-#define AX_MEMR_MDC BIT(0)
-#define AX_MEMR_MDIR BIT(1)
-#define AX_MEMR_MDI BIT(2)
-#define AX_MEMR_MDO BIT(3)
-#define AX_MEMR_EECS BIT(4)
-#define AX_MEMR_EEI BIT(5)
-#define AX_MEMR_EEO BIT(6)
-#define AX_MEMR_EECLK BIT(7)
-
-static void ax_handle_link_change(struct net_device *dev)
-{
- struct ax_device *ax = to_ax_dev(dev);
- struct phy_device *phy_dev = dev->phydev;
- int status_change = 0;
-
- if (phy_dev->link && ((ax->speed != phy_dev->speed) ||
- (ax->duplex != phy_dev->duplex))) {
-
- ax->speed = phy_dev->speed;
- ax->duplex = phy_dev->duplex;
- status_change = 1;
- }
-
- if (phy_dev->link != ax->link) {
- if (!phy_dev->link) {
- ax->speed = 0;
- ax->duplex = -1;
- }
- ax->link = phy_dev->link;
-
- status_change = 1;
- }
-
- if (status_change)
- phy_print_status(phy_dev);
-}
-
-static int ax_mii_probe(struct net_device *dev)
-{
- struct ax_device *ax = to_ax_dev(dev);
- struct phy_device *phy_dev = NULL;
- int ret;
-
- /* find the first phy */
- phy_dev = phy_find_first(ax->mii_bus);
- if (!phy_dev) {
- netdev_err(dev, "no PHY found\n");
- return -ENODEV;
- }
-
- ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change,
- PHY_INTERFACE_MODE_MII);
- if (ret) {
- netdev_err(dev, "Could not attach to PHY\n");
- return ret;
- }
-
- phy_set_max_speed(phy_dev, SPEED_100);
-
- netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
- phy_dev->drv->name, phydev_name(phy_dev), phy_dev->irq);
-
- return 0;
-}
-
-static void ax_phy_switch(struct net_device *dev, int on)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- struct ax_device *ax = to_ax_dev(dev);
-
- u8 reg_gpoc = ax->plat->gpoc_val;
-
- if (!!on)
- reg_gpoc &= ~AX_GPOC_PPDSET;
- else
- reg_gpoc |= AX_GPOC_PPDSET;
-
- ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17));
-}
-
-static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
-{
- struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
-
- if (level)
- ax->reg_memr |= AX_MEMR_MDC;
- else
- ax->reg_memr &= ~AX_MEMR_MDC;
-
- ei_outb(ax->reg_memr, ax->addr_memr);
-}
-
-static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
-{
- struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
-
- if (output)
- ax->reg_memr &= ~AX_MEMR_MDIR;
- else
- ax->reg_memr |= AX_MEMR_MDIR;
-
- ei_outb(ax->reg_memr, ax->addr_memr);
-}
-
-static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
-{
- struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
-
- if (value)
- ax->reg_memr |= AX_MEMR_MDO;
- else
- ax->reg_memr &= ~AX_MEMR_MDO;
-
- ei_outb(ax->reg_memr, ax->addr_memr);
-}
-
-static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
-{
- struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
- int reg_memr = ei_inb(ax->addr_memr);
-
- return reg_memr & AX_MEMR_MDI ? 1 : 0;
-}
-
-static const struct mdiobb_ops bb_ops = {
- .owner = THIS_MODULE,
- .set_mdc = ax_bb_mdc,
- .set_mdio_dir = ax_bb_dir,
- .set_mdio_data = ax_bb_set_data,
- .get_mdio_data = ax_bb_get_data,
-};
-
-static int ax_mii_init(struct net_device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev->dev.parent);
- struct ei_device *ei_local = netdev_priv(dev);
- struct ax_device *ax = to_ax_dev(dev);
- int err;
-
- ax->bb_ctrl.ops = &bb_ops;
- ax->addr_memr = ei_local->mem + AX_MEMR;
- ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
- if (!ax->mii_bus) {
- err = -ENOMEM;
- goto out;
- }
-
- ax->mii_bus->name = "ax88796_mii_bus";
- ax->mii_bus->parent = dev->dev.parent;
- snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
- pdev->name, pdev->id);
-
- err = mdiobus_register(ax->mii_bus);
- if (err)
- goto out_free_mdio_bitbang;
-
- return 0;
-
- out_free_mdio_bitbang:
- free_mdio_bitbang(ax->mii_bus);
- out:
- return err;
-}
-
-static int ax_open(struct net_device *dev)
-{
- struct ax_device *ax = to_ax_dev(dev);
- int ret;
-
- netdev_dbg(dev, "open\n");
-
- ret = ax_mii_init(dev);
- if (ret)
- goto failed_mii;
-
- if (ax->plat->check_irq)
- ret = request_irq(dev->irq, ax_ei_interrupt_filtered,
- ax->irqflags, dev->name, dev);
- else
- ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
- dev->name, dev);
- if (ret)
- goto failed_request_irq;
-
- /* turn the phy on (if turned off) */
- ax_phy_switch(dev, 1);
-
- ret = ax_mii_probe(dev);
- if (ret)
- goto failed_mii_probe;
- phy_start(dev->phydev);
-
- ret = ax_ei_open(dev);
- if (ret)
- goto failed_ax_ei_open;
-
- ax->running = 1;
-
- return 0;
-
- failed_ax_ei_open:
- phy_disconnect(dev->phydev);
- failed_mii_probe:
- ax_phy_switch(dev, 0);
- free_irq(dev->irq, dev);
- failed_request_irq:
- /* unregister mdiobus */
- mdiobus_unregister(ax->mii_bus);
- free_mdio_bitbang(ax->mii_bus);
- failed_mii:
- return ret;
-}
-
-static int ax_close(struct net_device *dev)
-{
- struct ax_device *ax = to_ax_dev(dev);
-
- netdev_dbg(dev, "close\n");
-
- ax->running = 0;
- wmb();
-
- ax_ei_close(dev);
-
- /* turn the phy off */
- ax_phy_switch(dev, 0);
- phy_disconnect(dev->phydev);
-
- free_irq(dev->irq, dev);
-
- mdiobus_unregister(ax->mii_bus);
- free_mdio_bitbang(ax->mii_bus);
- return 0;
-}
-
-static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
- struct phy_device *phy_dev = dev->phydev;
-
- if (!netif_running(dev))
- return -EINVAL;
-
- if (!phy_dev)
- return -ENODEV;
-
- return phy_mii_ioctl(phy_dev, req, cmd);
-}
-
-/* ethtool ops */
-
-static void ax_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
-{
- struct platform_device *pdev = to_platform_device(dev->dev.parent);
-
- strscpy(info->driver, DRV_NAME, sizeof(info->driver));
- strscpy(info->version, DRV_VERSION, sizeof(info->version));
- strscpy(info->bus_info, pdev->name, sizeof(info->bus_info));
-}
-
-static u32 ax_get_msglevel(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- return ei_local->msg_enable;
-}
-
-static void ax_set_msglevel(struct net_device *dev, u32 v)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- ei_local->msg_enable = v;
-}
-
-static const struct ethtool_ops ax_ethtool_ops = {
- .get_drvinfo = ax_get_drvinfo,
- .get_link = ethtool_op_get_link,
- .get_ts_info = ethtool_op_get_ts_info,
- .get_msglevel = ax_get_msglevel,
- .set_msglevel = ax_set_msglevel,
- .get_link_ksettings = phy_ethtool_get_link_ksettings,
- .set_link_ksettings = phy_ethtool_set_link_ksettings,
-};
-
-#ifdef CONFIG_AX88796_93CX6
-static void ax_eeprom_register_read(struct eeprom_93cx6 *eeprom)
-{
- struct ei_device *ei_local = eeprom->data;
- u8 reg = ei_inb(ei_local->mem + AX_MEMR);
-
- eeprom->reg_data_in = reg & AX_MEMR_EEI;
- eeprom->reg_data_out = reg & AX_MEMR_EEO; /* Input pin */
- eeprom->reg_data_clock = reg & AX_MEMR_EECLK;
- eeprom->reg_chip_select = reg & AX_MEMR_EECS;
-}
-
-static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
-{
- struct ei_device *ei_local = eeprom->data;
- u8 reg = ei_inb(ei_local->mem + AX_MEMR);
-
- reg &= ~(AX_MEMR_EEI | AX_MEMR_EECLK | AX_MEMR_EECS);
-
- if (eeprom->reg_data_in)
- reg |= AX_MEMR_EEI;
- if (eeprom->reg_data_clock)
- reg |= AX_MEMR_EECLK;
- if (eeprom->reg_chip_select)
- reg |= AX_MEMR_EECS;
-
- ei_outb(reg, ei_local->mem + AX_MEMR);
- udelay(10);
-}
-#endif
-
-static const struct net_device_ops ax_netdev_ops = {
- .ndo_open = ax_open,
- .ndo_stop = ax_close,
- .ndo_eth_ioctl = ax_ioctl,
-
- .ndo_start_xmit = ax_ei_start_xmit,
- .ndo_tx_timeout = ax_ei_tx_timeout,
- .ndo_get_stats = ax_ei_get_stats,
- .ndo_set_rx_mode = ax_ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ax_ei_poll,
-#endif
-};
-
-/* setup code */
-
-static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
-{
- void __iomem *ioaddr = ei_local->mem;
- struct ax_device *ax = to_ax_dev(dev);
-
- /* Select page 0 */
- ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_STOP, ioaddr + E8390_CMD);
-
- /* set to byte access */
- ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
- ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
-}
-
-/*
- * ax_init_dev
- *
- * initialise the specified device, taking care to note the MAC
- * address it may already have (if configured), ensure
- * the device is ready to be used by lib8390.c and registerd with
- * the network layer.
- */
-static int ax_init_dev(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- struct ax_device *ax = to_ax_dev(dev);
- void __iomem *ioaddr = ei_local->mem;
- unsigned int start_page;
- unsigned int stop_page;
- int ret;
- int i;
-
- ret = ax_initial_check(dev);
- if (ret)
- goto err_out;
-
- /* setup goes here */
-
- ax_initial_setup(dev, ei_local);
-
- /* read the mac from the card prom if we need it */
-
- if (ax->plat->flags & AXFLG_HAS_EEPROM) {
- unsigned char SA_prom[32];
-
- ei_outb(6, ioaddr + EN0_RCNTLO);
- ei_outb(0, ioaddr + EN0_RCNTHI);
- ei_outb(0, ioaddr + EN0_RSARLO);
- ei_outb(0, ioaddr + EN0_RSARHI);
- ei_outb(E8390_RREAD + E8390_START, ioaddr + NE_CMD);
- for (i = 0; i < sizeof(SA_prom); i += 2) {
- SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
- SA_prom[i + 1] = ei_inb(ioaddr + NE_DATAPORT);
- }
- ei_outb(ENISR_RDC, ioaddr + EN0_ISR); /* Ack intr. */
-
- if (ax->plat->wordlength == 2)
- for (i = 0; i < 16; i++)
- SA_prom[i] = SA_prom[i+i];
-
- eth_hw_addr_set(dev, SA_prom);
- }
-
-#ifdef CONFIG_AX88796_93CX6
- if (ax->plat->flags & AXFLG_HAS_93CX6) {
- unsigned char mac_addr[ETH_ALEN];
- struct eeprom_93cx6 eeprom;
-
- eeprom.data = ei_local;
- eeprom.register_read = ax_eeprom_register_read;
- eeprom.register_write = ax_eeprom_register_write;
- eeprom.width = PCI_EEPROM_WIDTH_93C56;
-
- eeprom_93cx6_multiread(&eeprom, 0,
- (__le16 __force *)mac_addr,
- sizeof(mac_addr) >> 1);
-
- eth_hw_addr_set(dev, mac_addr);
- }
-#endif
- if (ax->plat->wordlength == 2) {
- /* We must set the 8390 for word mode. */
- ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
- } else {
- start_page = NE1SM_START_PG;
- stop_page = NE1SM_STOP_PG;
- }
-
- /* load the mac-address from the device */
- if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
- u8 addr[ETH_ALEN];
-
- ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
- ei_local->mem + E8390_CMD); /* 0x61 */
- for (i = 0; i < ETH_ALEN; i++)
- addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
- eth_hw_addr_set(dev, addr);
- }
-
- if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
- ax->plat->mac_addr)
- eth_hw_addr_set(dev, ax->plat->mac_addr);
-
- if (!is_valid_ether_addr(dev->dev_addr)) {
- eth_hw_addr_random(dev);
- dev_info(&dev->dev, "Using random MAC address: %pM\n",
- dev->dev_addr);
- }
-
- ax_reset_8390(dev);
-
- ei_local->name = "AX88796";
- ei_local->tx_start_page = start_page;
- ei_local->stop_page = stop_page;
- ei_local->word16 = (ax->plat->wordlength == 2);
- ei_local->rx_start_page = start_page + TX_PAGES;
-
-#ifdef PACKETBUF_MEMSIZE
- /* Allow the packet buffer size to be overridden by know-it-alls. */
- ei_local->stop_page = ei_local->tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
- ei_local->reset_8390 = &ax_reset_8390;
- if (ax->plat->block_input)
- ei_local->block_input = ax->plat->block_input;
- else
- ei_local->block_input = &ax_block_input;
- if (ax->plat->block_output)
- ei_local->block_output = ax->plat->block_output;
- else
- ei_local->block_output = &ax_block_output;
- ei_local->get_8390_hdr = &ax_get_8390_hdr;
- ei_local->priv = 0;
-
- dev->netdev_ops = &ax_netdev_ops;
- dev->ethtool_ops = &ax_ethtool_ops;
-
- ax_NS8390_init(dev, 0);
-
- ret = register_netdev(dev);
- if (ret)
- goto err_out;
-
- netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",
- ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr,
- dev->dev_addr);
-
- return 0;
-
- err_out:
- return ret;
-}
-
-static void ax_remove(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct ei_device *ei_local = netdev_priv(dev);
- struct ax_device *ax = to_ax_dev(dev);
- struct resource *mem;
-
- unregister_netdev(dev);
-
- iounmap(ei_local->mem);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
-
- if (ax->map2) {
- iounmap(ax->map2);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- release_mem_region(mem->start, resource_size(mem));
- }
-
- platform_set_drvdata(pdev, NULL);
- free_netdev(dev);
-}
-
-/*
- * ax_probe
- *
- * This is the entry point when the platform device system uses to
- * notify us of a new device to attach to. Allocate memory, find the
- * resources and information passed, and map the necessary registers.
- */
-static int ax_probe(struct platform_device *pdev)
-{
- struct net_device *dev;
- struct ei_device *ei_local;
- struct ax_device *ax;
- struct resource *irq, *mem, *mem2;
- unsigned long mem_size, mem2_size = 0;
- int ret = 0;
-
- dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
- if (dev == NULL)
- return -ENOMEM;
-
- /* ok, let's setup our device */
- SET_NETDEV_DEV(dev, &pdev->dev);
- ei_local = netdev_priv(dev);
- ax = to_ax_dev(dev);
-
- ax->plat = dev_get_platdata(&pdev->dev);
- platform_set_drvdata(pdev, dev);
-
- ei_local->rxcr_base = ax->plat->rcr_val;
-
- /* find the platform resources */
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq) {
- dev_err(&pdev->dev, "no IRQ specified\n");
- ret = -ENXIO;
- goto exit_mem;
- }
-
- dev->irq = irq->start;
- ax->irqflags = irq->flags & IRQF_TRIGGER_MASK;
-
- if (irq->flags & IORESOURCE_IRQ_SHAREABLE)
- ax->irqflags |= IRQF_SHARED;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "no MEM specified\n");
- ret = -ENXIO;
- goto exit_mem;
- }
-
- mem_size = resource_size(mem);
-
- /*
- * setup the register offsets from either the platform data or
- * by using the size of the resource provided
- */
- if (ax->plat->reg_offsets)
- ei_local->reg_offset = ax->plat->reg_offsets;
- else {
- ei_local->reg_offset = ax->reg_offsets;
- for (ret = 0; ret < 0x18; ret++)
- ax->reg_offsets[ret] = (mem_size / 0x18) * ret;
- }
-
- if (!request_mem_region(mem->start, mem_size, pdev->name)) {
- dev_err(&pdev->dev, "cannot reserve registers\n");
- ret = -ENXIO;
- goto exit_mem;
- }
-
- ei_local->mem = ioremap(mem->start, mem_size);
- dev->base_addr = (unsigned long)ei_local->mem;
-
- if (ei_local->mem == NULL) {
- dev_err(&pdev->dev, "Cannot ioremap area %pR\n", mem);
-
- ret = -ENXIO;
- goto exit_req;
- }
-
- /* look for reset area */
- mem2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!mem2) {
- if (!ax->plat->reg_offsets) {
- for (ret = 0; ret < 0x20; ret++)
- ax->reg_offsets[ret] = (mem_size / 0x20) * ret;
- }
- } else {
- mem2_size = resource_size(mem2);
-
- if (!request_mem_region(mem2->start, mem2_size, pdev->name)) {
- dev_err(&pdev->dev, "cannot reserve registers\n");
- ret = -ENXIO;
- goto exit_mem1;
- }
-
- ax->map2 = ioremap(mem2->start, mem2_size);
- if (!ax->map2) {
- dev_err(&pdev->dev, "cannot map reset register\n");
- ret = -ENXIO;
- goto exit_mem2;
- }
-
- ei_local->reg_offset[0x1f] = ax->map2 - ei_local->mem;
- }
-
- /* got resources, now initialise and register device */
- ret = ax_init_dev(dev);
- if (!ret)
- return 0;
-
- if (!ax->map2)
- goto exit_mem1;
-
- iounmap(ax->map2);
-
- exit_mem2:
- if (mem2)
- release_mem_region(mem2->start, mem2_size);
-
- exit_mem1:
- iounmap(ei_local->mem);
-
- exit_req:
- release_mem_region(mem->start, mem_size);
-
- exit_mem:
- platform_set_drvdata(pdev, NULL);
- free_netdev(dev);
-
- return ret;
-}
-
-/* suspend and resume */
-
-#ifdef CONFIG_PM
-static int ax_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct net_device *ndev = platform_get_drvdata(dev);
- struct ax_device *ax = to_ax_dev(ndev);
-
- ax->resume_open = ax->running;
-
- netif_device_detach(ndev);
- ax_close(ndev);
-
- return 0;
-}
-
-static int ax_resume(struct platform_device *pdev)
-{
- struct net_device *ndev = platform_get_drvdata(pdev);
- struct ax_device *ax = to_ax_dev(ndev);
-
- ax_initial_setup(ndev, netdev_priv(ndev));
- ax_NS8390_init(ndev, ax->resume_open);
- netif_device_attach(ndev);
-
- if (ax->resume_open)
- ax_open(ndev);
-
- return 0;
-}
-
-#else
-#define ax_suspend NULL
-#define ax_resume NULL
-#endif
-
-static struct platform_driver axdrv = {
- .driver = {
- .name = "ax88796",
- },
- .probe = ax_probe,
- .remove = ax_remove,
- .suspend = ax_suspend,
- .resume = ax_resume,
-};
-
-module_platform_driver(axdrv);
-
-MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:ax88796");
diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c
deleted file mode 100644
index e876fe523..000000000
--- a/drivers/net/ethernet/8390/etherh.c
+++ /dev/null
@@ -1,858 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/drivers/acorn/net/etherh.c
- *
- * Copyright (C) 2000-2002 Russell King
- *
- * NS8390 I-cubed EtherH and ANT EtherM specific driver
- * Thanks to I-Cubed for information on their cards.
- * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton
- * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan)
- * EtherM integration re-engineered by Russell King.
- *
- * Changelog:
- * 08-12-1996 RMK 1.00 Created
- * RMK 1.03 Added support for EtherLan500 cards
- * 23-11-1997 RMK 1.04 Added media autodetection
- * 16-04-1998 RMK 1.05 Improved media autodetection
- * 10-02-2000 RMK 1.06 Updated for 2.3.43
- * 13-05-2000 RMK 1.07 Updated for 2.3.99-pre8
- * 12-10-1999 CK/TEW EtherM driver first release
- * 21-12-2000 TTC EtherH/EtherM integration
- * 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver.
- * 03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/ecard.h>
-#include <asm/io.h>
-#include <asm/system_info.h>
-
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-
-#define ei_inb(_p) readb((void __iomem *)_p)
-#define ei_outb(_v,_p) writeb(_v,(void __iomem *)_p)
-#define ei_inb_p(_p) readb((void __iomem *)_p)
-#define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p)
-
-#define DRV_NAME "etherh"
-#define DRV_VERSION "1.11"
-
-static char version[] =
- "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
-
-#include "lib8390.c"
-
-struct etherh_priv {
- void __iomem *ioc_fast;
- void __iomem *memc;
- void __iomem *dma_base;
- unsigned int id;
- void __iomem *ctrl_port;
- unsigned char ctrl;
- u32 supported;
-};
-
-struct etherh_data {
- unsigned long ns8390_offset;
- unsigned long dataport_offset;
- unsigned long ctrlport_offset;
- int ctrl_ioc;
- const char name[16];
- u32 supported;
- unsigned char tx_start_page;
- unsigned char stop_page;
-};
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("EtherH/EtherM driver");
-MODULE_LICENSE("GPL");
-
-#define ETHERH500_DATAPORT 0x800 /* MEMC */
-#define ETHERH500_NS8390 0x000 /* MEMC */
-#define ETHERH500_CTRLPORT 0x800 /* IOC */
-
-#define ETHERH600_DATAPORT 0x040 /* MEMC */
-#define ETHERH600_NS8390 0x800 /* MEMC */
-#define ETHERH600_CTRLPORT 0x200 /* MEMC */
-
-#define ETHERH_CP_IE 1
-#define ETHERH_CP_IF 2
-#define ETHERH_CP_HEARTBEAT 2
-
-#define ETHERH_TX_START_PAGE 1
-#define ETHERH_STOP_PAGE 127
-
-/*
- * These came from CK/TEW
- */
-#define ETHERM_DATAPORT 0x200 /* MEMC */
-#define ETHERM_NS8390 0x800 /* MEMC */
-#define ETHERM_CTRLPORT 0x23c /* MEMC */
-
-#define ETHERM_TX_START_PAGE 64
-#define ETHERM_STOP_PAGE 127
-
-/* ------------------------------------------------------------------------ */
-
-#define etherh_priv(dev) \
- ((struct etherh_priv *)(((char *)netdev_priv(dev)) + sizeof(struct ei_device)))
-
-static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned char mask)
-{
- unsigned char ctrl = eh->ctrl | mask;
- eh->ctrl = ctrl;
- writeb(ctrl, eh->ctrl_port);
-}
-
-static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned char mask)
-{
- unsigned char ctrl = eh->ctrl & ~mask;
- eh->ctrl = ctrl;
- writeb(ctrl, eh->ctrl_port);
-}
-
-static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
-{
- return readb(eh->ctrl_port);
-}
-
-
-
-
-static void etherh_irq_enable(ecard_t *ec, int irqnr)
-{
- struct etherh_priv *eh = ec->irq_data;
-
- etherh_set_ctrl(eh, ETHERH_CP_IE);
-}
-
-static void etherh_irq_disable(ecard_t *ec, int irqnr)
-{
- struct etherh_priv *eh = ec->irq_data;
-
- etherh_clr_ctrl(eh, ETHERH_CP_IE);
-}
-
-static expansioncard_ops_t etherh_ops = {
- .irqenable = etherh_irq_enable,
- .irqdisable = etherh_irq_disable,
-};
-
-
-
-
-static void
-etherh_setif(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned long flags;
- void __iomem *addr;
-
- local_irq_save(flags);
-
- /* set the interface type */
- switch (etherh_priv(dev)->id) {
- case PROD_I3_ETHERLAN600:
- case PROD_I3_ETHERLAN600A:
- addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
-
- switch (dev->if_port) {
- case IF_PORT_10BASE2:
- writeb((readb(addr) & 0xf8) | 1, addr);
- break;
- case IF_PORT_10BASET:
- writeb((readb(addr) & 0xf8), addr);
- break;
- }
- break;
-
- case PROD_I3_ETHERLAN500:
- switch (dev->if_port) {
- case IF_PORT_10BASE2:
- etherh_clr_ctrl(etherh_priv(dev), ETHERH_CP_IF);
- break;
-
- case IF_PORT_10BASET:
- etherh_set_ctrl(etherh_priv(dev), ETHERH_CP_IF);
- break;
- }
- break;
-
- default:
- break;
- }
-
- local_irq_restore(flags);
-}
-
-static int
-etherh_getifstat(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *addr;
- int stat = 0;
-
- switch (etherh_priv(dev)->id) {
- case PROD_I3_ETHERLAN600:
- case PROD_I3_ETHERLAN600A:
- addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
- switch (dev->if_port) {
- case IF_PORT_10BASE2:
- stat = 1;
- break;
- case IF_PORT_10BASET:
- stat = readb(addr) & 4;
- break;
- }
- break;
-
- case PROD_I3_ETHERLAN500:
- switch (dev->if_port) {
- case IF_PORT_10BASE2:
- stat = 1;
- break;
- case IF_PORT_10BASET:
- stat = etherh_get_stat(etherh_priv(dev)) & ETHERH_CP_HEARTBEAT;
- break;
- }
- break;
-
- default:
- stat = 0;
- break;
- }
-
- return stat != 0;
-}
-
-/*
- * Configure the interface. Note that we ignore the other
- * parts of ifmap, since its mostly meaningless for this driver.
- */
-static int etherh_set_config(struct net_device *dev, struct ifmap *map)
-{
- switch (map->port) {
- case IF_PORT_10BASE2:
- case IF_PORT_10BASET:
- /*
- * If the user explicitly sets the interface
- * media type, turn off automedia detection.
- */
- dev->flags &= ~IFF_AUTOMEDIA;
- WRITE_ONCE(dev->if_port, map->port);
- break;
-
- default:
- return -EINVAL;
- }
-
- etherh_setif(dev);
-
- return 0;
-}
-
-/*
- * Reset the 8390 (hard reset). Note that we can't actually do this.
- */
-static void
-etherh_reset(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *addr = (void __iomem *)dev->base_addr;
-
- writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
-
- /*
- * See if we need to change the interface type.
- * Note that we use 'interface_num' as a flag
- * to indicate that we need to change the media.
- */
- if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) {
- ei_local->interface_num = 0;
-
- if (dev->if_port == IF_PORT_10BASET)
- dev->if_port = IF_PORT_10BASE2;
- else
- dev->if_port = IF_PORT_10BASET;
-
- etherh_setif(dev);
- }
-}
-
-/*
- * Write a block of data out to the 8390
- */
-static void
-etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned long dma_start;
- void __iomem *dma_base, *addr;
-
- if (ei_local->dmaing) {
- netdev_err(dev, "DMAing conflict in etherh_block_input: "
- " DMAstat %d irqlock %d\n",
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- /*
- * Make sure we have a round number of bytes if we're in word mode.
- */
- if (count & 1 && ei_local->word16)
- count++;
-
- ei_local->dmaing = 1;
-
- addr = (void __iomem *)dev->base_addr;
- dma_base = etherh_priv(dev)->dma_base;
-
- count = (count + 1) & ~1;
- writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
-
- writeb (0x42, addr + EN0_RCNTLO);
- writeb (0x00, addr + EN0_RCNTHI);
- writeb (0x42, addr + EN0_RSARLO);
- writeb (0x00, addr + EN0_RSARHI);
- writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
- udelay (1);
-
- writeb (ENISR_RDC, addr + EN0_ISR);
- writeb (count, addr + EN0_RCNTLO);
- writeb (count >> 8, addr + EN0_RCNTHI);
- writeb (0, addr + EN0_RSARLO);
- writeb (start_page, addr + EN0_RSARHI);
- writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
-
- if (ei_local->word16)
- writesw (dma_base, buf, count >> 1);
- else
- writesb (dma_base, buf, count);
-
- dma_start = jiffies;
-
- while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
- netdev_warn(dev, "timeout waiting for TX RDC\n");
- etherh_reset (dev);
- __NS8390_init (dev, 1);
- break;
- }
-
- writeb (ENISR_RDC, addr + EN0_ISR);
- ei_local->dmaing = 0;
-}
-
-/*
- * Read a block of data from the 8390
- */
-static void
-etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned char *buf;
- void __iomem *dma_base, *addr;
-
- if (ei_local->dmaing) {
- netdev_err(dev, "DMAing conflict in etherh_block_input: "
- " DMAstat %d irqlock %d\n",
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing = 1;
-
- addr = (void __iomem *)dev->base_addr;
- dma_base = etherh_priv(dev)->dma_base;
-
- buf = skb->data;
- writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
- writeb (count, addr + EN0_RCNTLO);
- writeb (count >> 8, addr + EN0_RCNTHI);
- writeb (ring_offset, addr + EN0_RSARLO);
- writeb (ring_offset >> 8, addr + EN0_RSARHI);
- writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
- if (ei_local->word16) {
- readsw (dma_base, buf, count >> 1);
- if (count & 1)
- buf[count - 1] = readb (dma_base);
- } else
- readsb (dma_base, buf, count);
-
- writeb (ENISR_RDC, addr + EN0_ISR);
- ei_local->dmaing = 0;
-}
-
-/*
- * Read a header from the 8390
- */
-static void
-etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *dma_base, *addr;
-
- if (ei_local->dmaing) {
- netdev_err(dev, "DMAing conflict in etherh_get_header: "
- " DMAstat %d irqlock %d\n",
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing = 1;
-
- addr = (void __iomem *)dev->base_addr;
- dma_base = etherh_priv(dev)->dma_base;
-
- writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
- writeb (sizeof (*hdr), addr + EN0_RCNTLO);
- writeb (0, addr + EN0_RCNTHI);
- writeb (0, addr + EN0_RSARLO);
- writeb (ring_page, addr + EN0_RSARHI);
- writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
- if (ei_local->word16)
- readsw (dma_base, hdr, sizeof (*hdr) >> 1);
- else
- readsb (dma_base, hdr, sizeof (*hdr));
-
- writeb (ENISR_RDC, addr + EN0_ISR);
- ei_local->dmaing = 0;
-}
-
-/*
- * Open/initialize the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-static int
-etherh_open(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
- return -EAGAIN;
-
- /*
- * Make sure that we aren't going to change the
- * media type on the next reset - we are about to
- * do automedia manually now.
- */
- ei_local->interface_num = 0;
-
- /*
- * If we are doing automedia detection, do it now.
- * This is more reliable than the 8390's detection.
- */
- if (dev->flags & IFF_AUTOMEDIA) {
- dev->if_port = IF_PORT_10BASET;
- etherh_setif(dev);
- mdelay(1);
- if (!etherh_getifstat(dev)) {
- dev->if_port = IF_PORT_10BASE2;
- etherh_setif(dev);
- }
- } else
- etherh_setif(dev);
-
- etherh_reset(dev);
- __ei_open(dev);
-
- return 0;
-}
-
-/*
- * The inverse routine to etherh_open().
- */
-static int
-etherh_close(struct net_device *dev)
-{
- __ei_close (dev);
- free_irq (dev->irq, dev);
- return 0;
-}
-
-/*
- * Read the ethernet address string from the on board rom.
- * This is an ascii string...
- */
-static int etherh_addr(char *addr, struct expansion_card *ec)
-{
- struct in_chunk_dir cd;
- char *s;
-
- if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
- printk(KERN_ERR "%s: unable to read module description string\n",
- dev_name(&ec->dev));
- goto no_addr;
- }
-
- s = strchr(cd.d.string, '(');
- if (s) {
- int i;
-
- for (i = 0; i < 6; i++) {
- addr[i] = simple_strtoul(s + 1, &s, 0x10);
- if (*s != (i == 5? ')' : ':'))
- break;
- }
-
- if (i == 6)
- return 0;
- }
-
- printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
- dev_name(&ec->dev), cd.d.string);
-
- no_addr:
- return -ENODEV;
-}
-
-/*
- * Create an ethernet address from the system serial number.
- */
-static int __init etherm_addr(char *addr)
-{
- unsigned int serial;
-
- if (system_serial_low == 0 && system_serial_high == 0)
- return -ENODEV;
-
- serial = system_serial_low | system_serial_high;
-
- addr[0] = 0;
- addr[1] = 0;
- addr[2] = 0xa4;
- addr[3] = 0x10 + (serial >> 24);
- addr[4] = serial >> 16;
- addr[5] = serial >> 8;
- return 0;
-}
-
-static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- strscpy(info->driver, DRV_NAME, sizeof(info->driver));
- strscpy(info->version, DRV_VERSION, sizeof(info->version));
- strscpy(info->bus_info, dev_name(dev->dev.parent),
- sizeof(info->bus_info));
-}
-
-static int etherh_get_link_ksettings(struct net_device *dev,
- struct ethtool_link_ksettings *cmd)
-{
- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
- etherh_priv(dev)->supported);
- cmd->base.speed = SPEED_10;
- cmd->base.duplex = DUPLEX_HALF;
- cmd->base.port = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC;
- cmd->base.autoneg = (dev->flags & IFF_AUTOMEDIA ? AUTONEG_ENABLE :
- AUTONEG_DISABLE);
- return 0;
-}
-
-static int etherh_set_link_ksettings(struct net_device *dev,
- const struct ethtool_link_ksettings *cmd)
-{
- switch (cmd->base.autoneg) {
- case AUTONEG_ENABLE:
- dev->flags |= IFF_AUTOMEDIA;
- break;
-
- case AUTONEG_DISABLE:
- switch (cmd->base.port) {
- case PORT_TP:
- dev->if_port = IF_PORT_10BASET;
- break;
-
- case PORT_BNC:
- dev->if_port = IF_PORT_10BASE2;
- break;
-
- default:
- return -EINVAL;
- }
- dev->flags &= ~IFF_AUTOMEDIA;
- break;
-
- default:
- return -EINVAL;
- }
-
- etherh_setif(dev);
-
- return 0;
-}
-
-static u32 etherh_get_msglevel(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- return ei_local->msg_enable;
-}
-
-static void etherh_set_msglevel(struct net_device *dev, u32 v)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- ei_local->msg_enable = v;
-}
-
-static const struct ethtool_ops etherh_ethtool_ops = {
- .get_drvinfo = etherh_get_drvinfo,
- .get_ts_info = ethtool_op_get_ts_info,
- .get_msglevel = etherh_get_msglevel,
- .set_msglevel = etherh_set_msglevel,
- .get_link_ksettings = etherh_get_link_ksettings,
- .set_link_ksettings = etherh_set_link_ksettings,
-};
-
-static const struct net_device_ops etherh_netdev_ops = {
- .ndo_open = etherh_open,
- .ndo_stop = etherh_close,
- .ndo_set_config = etherh_set_config,
- .ndo_start_xmit = __ei_start_xmit,
- .ndo_tx_timeout = __ei_tx_timeout,
- .ndo_get_stats = __ei_get_stats,
- .ndo_set_rx_mode = __ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = __ei_poll,
-#endif
-};
-
-static u32 etherh_regoffsets[16];
-static u32 etherm_regoffsets[16];
-
-static int
-etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
- const struct etherh_data *data = id->data;
- struct ei_device *ei_local;
- struct net_device *dev;
- struct etherh_priv *eh;
- u8 addr[ETH_ALEN];
- int ret;
-
- ret = ecard_request_resources(ec);
- if (ret)
- goto out;
-
- dev = ____alloc_ei_netdev(sizeof(struct etherh_priv));
- if (!dev) {
- ret = -ENOMEM;
- goto release;
- }
-
- SET_NETDEV_DEV(dev, &ec->dev);
-
- dev->netdev_ops = ðerh_netdev_ops;
- dev->irq = ec->irq;
- dev->ethtool_ops = ðerh_ethtool_ops;
-
- if (data->supported & SUPPORTED_Autoneg)
- dev->flags |= IFF_AUTOMEDIA;
- if (data->supported & SUPPORTED_TP) {
- dev->flags |= IFF_PORTSEL;
- dev->if_port = IF_PORT_10BASET;
- } else if (data->supported & SUPPORTED_BNC) {
- dev->flags |= IFF_PORTSEL;
- dev->if_port = IF_PORT_10BASE2;
- } else
- dev->if_port = IF_PORT_UNKNOWN;
-
- eh = etherh_priv(dev);
- eh->supported = data->supported;
- eh->ctrl = 0;
- eh->id = ec->cid.product;
- eh->memc = ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE);
- if (!eh->memc) {
- ret = -ENOMEM;
- goto free;
- }
-
- eh->ctrl_port = eh->memc;
- if (data->ctrl_ioc) {
- eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE);
- if (!eh->ioc_fast) {
- ret = -ENOMEM;
- goto free;
- }
- eh->ctrl_port = eh->ioc_fast;
- }
-
- dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
- eh->dma_base = eh->memc + data->dataport_offset;
- eh->ctrl_port += data->ctrlport_offset;
-
- /*
- * IRQ and control port handling - only for non-NIC slot cards.
- */
- if (ec->slot_no != 8) {
- ecard_setirq(ec, ðerh_ops, eh);
- } else {
- /*
- * If we're in the NIC slot, make sure the IRQ is enabled
- */
- etherh_set_ctrl(eh, ETHERH_CP_IE);
- }
-
- ei_local = netdev_priv(dev);
- spin_lock_init(&ei_local->page_lock);
-
- if (ec->cid.product == PROD_ANT_ETHERM) {
- etherm_addr(addr);
- ei_local->reg_offset = etherm_regoffsets;
- } else {
- etherh_addr(addr, ec);
- ei_local->reg_offset = etherh_regoffsets;
- }
- eth_hw_addr_set(dev, addr);
-
- ei_local->name = dev->name;
- ei_local->word16 = 1;
- ei_local->tx_start_page = data->tx_start_page;
- ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
- ei_local->stop_page = data->stop_page;
- ei_local->reset_8390 = etherh_reset;
- ei_local->block_input = etherh_block_input;
- ei_local->block_output = etherh_block_output;
- ei_local->get_8390_hdr = etherh_get_header;
- ei_local->interface_num = 0;
-
- etherh_reset(dev);
- __NS8390_init(dev, 0);
-
- ret = register_netdev(dev);
- if (ret)
- goto free;
-
- netdev_info(dev, "%s in slot %d, %pM\n",
- data->name, ec->slot_no, dev->dev_addr);
-
- ecard_set_drvdata(ec, dev);
-
- return 0;
-
- free:
- free_netdev(dev);
- release:
- ecard_release_resources(ec);
- out:
- return ret;
-}
-
-static void etherh_remove(struct expansion_card *ec)
-{
- struct net_device *dev = ecard_get_drvdata(ec);
-
- ecard_set_drvdata(ec, NULL);
-
- unregister_netdev(dev);
-
- free_netdev(dev);
-
- ecard_release_resources(ec);
-}
-
-static struct etherh_data etherm_data = {
- .ns8390_offset = ETHERM_NS8390,
- .dataport_offset = ETHERM_NS8390 + ETHERM_DATAPORT,
- .ctrlport_offset = ETHERM_NS8390 + ETHERM_CTRLPORT,
- .name = "ANT EtherM",
- .supported = SUPPORTED_10baseT_Half,
- .tx_start_page = ETHERM_TX_START_PAGE,
- .stop_page = ETHERM_STOP_PAGE,
-};
-
-static struct etherh_data etherlan500_data = {
- .ns8390_offset = ETHERH500_NS8390,
- .dataport_offset = ETHERH500_NS8390 + ETHERH500_DATAPORT,
- .ctrlport_offset = ETHERH500_CTRLPORT,
- .ctrl_ioc = 1,
- .name = "i3 EtherH 500",
- .supported = SUPPORTED_10baseT_Half,
- .tx_start_page = ETHERH_TX_START_PAGE,
- .stop_page = ETHERH_STOP_PAGE,
-};
-
-static struct etherh_data etherlan600_data = {
- .ns8390_offset = ETHERH600_NS8390,
- .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT,
- .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
- .name = "i3 EtherH 600",
- .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
- .tx_start_page = ETHERH_TX_START_PAGE,
- .stop_page = ETHERH_STOP_PAGE,
-};
-
-static struct etherh_data etherlan600a_data = {
- .ns8390_offset = ETHERH600_NS8390,
- .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT,
- .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
- .name = "i3 EtherH 600A",
- .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
- .tx_start_page = ETHERH_TX_START_PAGE,
- .stop_page = ETHERH_STOP_PAGE,
-};
-
-static const struct ecard_id etherh_ids[] = {
- { MANU_ANT, PROD_ANT_ETHERM, ðerm_data },
- { MANU_I3, PROD_I3_ETHERLAN500, ðerlan500_data },
- { MANU_I3, PROD_I3_ETHERLAN600, ðerlan600_data },
- { MANU_I3, PROD_I3_ETHERLAN600A, ðerlan600a_data },
- { 0xffff, 0xffff }
-};
-
-static struct ecard_driver etherh_driver = {
- .probe = etherh_probe,
- .remove = etherh_remove,
- .id_table = etherh_ids,
- .drv = {
- .name = DRV_NAME,
- },
-};
-
-static int __init etherh_init(void)
-{
- int i;
-
- for (i = 0; i < 16; i++) {
- etherh_regoffsets[i] = i << 2;
- etherm_regoffsets[i] = i << 5;
- }
-
- return ecard_register_driver(ðerh_driver);
-}
-
-static void __exit etherh_exit(void)
-{
- ecard_remove_driver(ðerh_driver);
-}
-
-module_init(etherh_init);
-module_exit(etherh_exit);
diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c
deleted file mode 100644
index fd9dcdc35..000000000
--- a/drivers/net/ethernet/8390/hydra.c
+++ /dev/null
@@ -1,274 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-/* New Hydra driver using generic 8390 core */
-/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */
-
-/* Peter De Schrijver (p2@mind.be) */
-/* Oldenburg 2000 */
-
-/* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a */
-/* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM */
-/* and 10BASE-2 (thin coax) and AUI connectors. */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <linux/zorro.h>
-
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-#define ei_inb(port) in_8(port)
-#define ei_outb(val,port) out_8(port,val)
-#define ei_inb_p(port) in_8(port)
-#define ei_outb_p(val,port) out_8(port,val)
-
-static const char version[] =
- "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-#define NE_EN0_DCFG (0x0e*2)
-
-#define NESM_START_PG 0x0 /* First page of TX buffer */
-#define NESM_STOP_PG 0x40 /* Last page +1 of RX ring */
-
-#define HYDRA_NIC_BASE 0xffe1
-#define HYDRA_ADDRPROM 0xffc0
-#define HYDRA_VERSION "v3.0alpha"
-
-#define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8))
-
-
-static int hydra_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent);
-static int hydra_init(struct zorro_dev *z);
-static int hydra_open(struct net_device *dev);
-static int hydra_close(struct net_device *dev);
-static void hydra_reset_8390(struct net_device *dev);
-static void hydra_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page);
-static void hydra_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void hydra_block_output(struct net_device *dev, int count,
- const unsigned char *buf, int start_page);
-static void hydra_remove_one(struct zorro_dev *z);
-
-static struct zorro_device_id hydra_zorro_tbl[] = {
- { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
- { 0 }
-};
-MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl);
-
-static struct zorro_driver hydra_driver = {
- .name = "hydra",
- .id_table = hydra_zorro_tbl,
- .probe = hydra_init_one,
- .remove = hydra_remove_one,
-};
-
-static int hydra_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
-{
- int err;
-
- if (!request_mem_region(z->resource.start, 0x10000, "Hydra"))
- return -EBUSY;
- if ((err = hydra_init(z))) {
- release_mem_region(z->resource.start, 0x10000);
- return -EBUSY;
- }
- return 0;
-}
-
-static const struct net_device_ops hydra_netdev_ops = {
- .ndo_open = hydra_open,
- .ndo_stop = hydra_close,
-
- .ndo_start_xmit = __ei_start_xmit,
- .ndo_tx_timeout = __ei_tx_timeout,
- .ndo_get_stats = __ei_get_stats,
- .ndo_set_rx_mode = __ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = __ei_poll,
-#endif
-};
-
-static int hydra_init(struct zorro_dev *z)
-{
- struct net_device *dev;
- unsigned long board = (unsigned long)ZTWO_VADDR(z->resource.start);
- unsigned long ioaddr = board+HYDRA_NIC_BASE;
- const char name[] = "NE2000";
- int start_page, stop_page;
- u8 macaddr[ETH_ALEN];
- int j;
- int err;
-
- static u32 hydra_offsets[16] = {
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
- };
-
- dev = ____alloc_ei_netdev(0);
- if (!dev)
- return -ENOMEM;
-
- for (j = 0; j < ETH_ALEN; j++)
- macaddr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j));
- eth_hw_addr_set(dev, macaddr);
-
- /* We must set the 8390 for word mode. */
- z_writeb(0x4b, ioaddr + NE_EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
-
- dev->base_addr = ioaddr;
- dev->irq = IRQ_AMIGA_PORTS;
-
- /* Install the Interrupt handler */
- if (request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, "Hydra Ethernet",
- dev)) {
- free_netdev(dev);
- return -EAGAIN;
- }
-
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
- ei_status.word16 = 1;
- ei_status.bigendian = 1;
-
- ei_status.rx_start_page = start_page + TX_PAGES;
-
- ei_status.reset_8390 = hydra_reset_8390;
- ei_status.block_input = hydra_block_input;
- ei_status.block_output = hydra_block_output;
- ei_status.get_8390_hdr = hydra_get_8390_hdr;
- ei_status.reg_offset = hydra_offsets;
-
- dev->netdev_ops = &hydra_netdev_ops;
- __NS8390_init(dev, 0);
-
- err = register_netdev(dev);
- if (err) {
- free_irq(IRQ_AMIGA_PORTS, dev);
- free_netdev(dev);
- return err;
- }
-
- zorro_set_drvdata(z, dev);
-
- pr_info("%s: Hydra at %pR, address %pM (hydra.c " HYDRA_VERSION ")\n",
- dev->name, &z->resource, dev->dev_addr);
-
- return 0;
-}
-
-static int hydra_open(struct net_device *dev)
-{
- __ei_open(dev);
- return 0;
-}
-
-static int hydra_close(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n");
- __ei_close(dev);
- return 0;
-}
-
-static void hydra_reset_8390(struct net_device *dev)
-{
- netdev_info(dev, "Hydra hw reset not there\n");
-}
-
-static void hydra_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page)
-{
- int nic_base = dev->base_addr;
- short *ptrs;
- unsigned long hdr_start= (nic_base-HYDRA_NIC_BASE) +
- ((ring_page - NESM_START_PG)<<8);
- ptrs = (short *)hdr;
-
- *(ptrs++) = z_readw(hdr_start);
- *((short *)hdr) = WORDSWAP(*((short *)hdr));
- hdr_start += 2;
- *(ptrs++) = z_readw(hdr_start);
- *((short *)hdr+1) = WORDSWAP(*((short *)hdr+1));
-}
-
-static void hydra_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- unsigned long nic_base = dev->base_addr;
- unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
- unsigned long xfer_start = mem_base + ring_offset - (NESM_START_PG<<8);
-
- if (count&1)
- count++;
-
- if (xfer_start+count > mem_base + (NESM_STOP_PG<<8)) {
- int semi_count = (mem_base + (NESM_STOP_PG<<8)) - xfer_start;
-
- z_memcpy_fromio(skb->data,xfer_start,semi_count);
- count -= semi_count;
- z_memcpy_fromio(skb->data+semi_count, mem_base, count);
- } else
- z_memcpy_fromio(skb->data, xfer_start,count);
-
-}
-
-static void hydra_block_output(struct net_device *dev, int count,
- const unsigned char *buf, int start_page)
-{
- unsigned long nic_base = dev->base_addr;
- unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
-
- if (count&1)
- count++;
-
- z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
-}
-
-static void hydra_remove_one(struct zorro_dev *z)
-{
- struct net_device *dev = zorro_get_drvdata(z);
-
- unregister_netdev(dev);
- free_irq(IRQ_AMIGA_PORTS, dev);
- release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000);
- free_netdev(dev);
-}
-
-static int __init hydra_init_module(void)
-{
- return zorro_register_driver(&hydra_driver);
-}
-
-static void __exit hydra_cleanup_module(void)
-{
- zorro_unregister_driver(&hydra_driver);
-}
-
-module_init(hydra_init_module);
-module_exit(hydra_cleanup_module);
-
-MODULE_DESCRIPTION("Zorro-II Hydra 8390 ethernet driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
deleted file mode 100644
index 4a0a095a1..000000000
--- a/drivers/net/ethernet/8390/mac8390.c
+++ /dev/null
@@ -1,848 +0,0 @@
-// SPDX-License-Identifier: GPL-1.0+
-/* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike)
- Ethernet cards on Linux */
-/* Based on the former daynaport.c driver, by Alan Cox. Some code
- taken from or inspired by skeleton.c by Donald Becker, acenic.c by
- Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker. */
-
-/* 2000-02-28: support added for Dayna and Kinetics cards by
- A.G.deWijn@phys.uu.nl */
-/* 2000-04-04: support added for Dayna2 by bart@etpmod.phys.tue.nl */
-/* 2001-04-18: support for DaynaPort E/LC-M by rayk@knightsmanor.org */
-/* 2001-05-15: support for Cabletron ported from old daynaport driver
- * and fixed access to Sonic Sys card which masquerades as a Farallon
- * by rayk@knightsmanor.org */
-/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */
-/* 2003-12-26: Make sure Asante cards always work. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/nubus.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-
-#include <asm/dma.h>
-#include <asm/hwtest.h>
-#include <asm/macints.h>
-
-static char version[] =
- "v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
-
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-#define ei_inb(port) in_8(port)
-#define ei_outb(val, port) out_8(port, val)
-#define ei_inb_p(port) in_8(port)
-#define ei_outb_p(val, port) out_8(port, val)
-
-#include "lib8390.c"
-
-#define WD_START_PG 0x00 /* First page of TX buffer */
-#define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */
-#define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */
-#define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG
- /* First page of TX buffer */
-
-/*
- * Unfortunately it seems we have to hardcode these for the moment
- * Shouldn't the card know about this?
- * Does anyone know where to read it off the card?
- * Do we trust the data provided by the card?
- */
-
-#define DAYNA_8390_BASE 0x80000
-#define DAYNA_8390_MEM 0x00000
-
-#define CABLETRON_8390_BASE 0x90000
-#define CABLETRON_8390_MEM 0x00000
-
-#define INTERLAN_8390_BASE 0xE0000
-#define INTERLAN_8390_MEM 0xD0000
-
-enum mac8390_type {
- MAC8390_NONE = -1,
- MAC8390_APPLE,
- MAC8390_ASANTE,
- MAC8390_FARALLON,
- MAC8390_CABLETRON,
- MAC8390_DAYNA,
- MAC8390_INTERLAN,
- MAC8390_KINETICS,
-};
-
-static const char *cardname[] = {
- "apple",
- "asante",
- "farallon",
- "cabletron",
- "dayna",
- "interlan",
- "kinetics",
-};
-
-static const int word16[] = {
- 1, /* apple */
- 1, /* asante */
- 1, /* farallon */
- 1, /* cabletron */
- 0, /* dayna */
- 1, /* interlan */
- 0, /* kinetics */
-};
-
-/* on which cards do we use NuBus resources? */
-static const int useresources[] = {
- 1, /* apple */
- 1, /* asante */
- 1, /* farallon */
- 0, /* cabletron */
- 0, /* dayna */
- 0, /* interlan */
- 0, /* kinetics */
-};
-
-enum mac8390_access {
- ACCESS_UNKNOWN = 0,
- ACCESS_32,
- ACCESS_16,
-};
-
-extern int mac8390_memtest(struct net_device *dev);
-static int mac8390_initdev(struct net_device *dev, struct nubus_board *board,
- enum mac8390_type type);
-
-static int mac8390_open(struct net_device *dev);
-static int mac8390_close(struct net_device *dev);
-static void mac8390_no_reset(struct net_device *dev);
-static void interlan_reset(struct net_device *dev);
-
-/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/
-static void sane_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page);
-static void sane_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void sane_block_output(struct net_device *dev, int count,
- const unsigned char *buf, const int start_page);
-
-/* dayna_memcpy to and from card */
-static void dayna_memcpy_fromcard(struct net_device *dev, void *to,
- int from, int count);
-static void dayna_memcpy_tocard(struct net_device *dev, int to,
- const void *from, int count);
-
-/* Dayna - Dayna/Kinetics use this */
-static void dayna_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page);
-static void dayna_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void dayna_block_output(struct net_device *dev, int count,
- const unsigned char *buf, int start_page);
-
-/* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */
-static void slow_sane_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page);
-static void slow_sane_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void slow_sane_block_output(struct net_device *dev, int count,
- const unsigned char *buf, int start_page);
-static void word_memcpy_tocard(unsigned long tp, const void *fp, int count);
-static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
-
-static enum mac8390_type mac8390_ident(struct nubus_rsrc *fres)
-{
- switch (fres->dr_sw) {
- case NUBUS_DRSW_3COM:
- switch (fres->dr_hw) {
- case NUBUS_DRHW_APPLE_SONIC_NB:
- case NUBUS_DRHW_APPLE_SONIC_LC:
- case NUBUS_DRHW_SONNET:
- return MAC8390_NONE;
- default:
- return MAC8390_APPLE;
- }
-
- case NUBUS_DRSW_APPLE:
- switch (fres->dr_hw) {
- case NUBUS_DRHW_ASANTE_LC:
- return MAC8390_NONE;
- case NUBUS_DRHW_CABLETRON:
- return MAC8390_CABLETRON;
- default:
- return MAC8390_APPLE;
- }
-
- case NUBUS_DRSW_ASANTE:
- return MAC8390_ASANTE;
-
- case NUBUS_DRSW_TECHWORKS:
- case NUBUS_DRSW_DAYNA2:
- case NUBUS_DRSW_DAYNA_LC:
- if (fres->dr_hw == NUBUS_DRHW_CABLETRON)
- return MAC8390_CABLETRON;
- else
- return MAC8390_APPLE;
-
- case NUBUS_DRSW_FARALLON:
- return MAC8390_FARALLON;
-
- case NUBUS_DRSW_KINETICS:
- switch (fres->dr_hw) {
- case NUBUS_DRHW_INTERLAN:
- return MAC8390_INTERLAN;
- default:
- return MAC8390_KINETICS;
- }
-
- case NUBUS_DRSW_DAYNA:
- /*
- * These correspond to Dayna Sonic cards
- * which use the macsonic driver
- */
- if (fres->dr_hw == NUBUS_DRHW_SMC9194 ||
- fres->dr_hw == NUBUS_DRHW_INTERLAN)
- return MAC8390_NONE;
- else
- return MAC8390_DAYNA;
- }
- return MAC8390_NONE;
-}
-
-static enum mac8390_access mac8390_testio(unsigned long membase)
-{
- u32 outdata = 0xA5A0B5B0;
- u32 indata = 0;
-
- /* Try writing 32 bits */
- nubus_writel(outdata, membase);
- /* Now read it back */
- indata = nubus_readl(membase);
- if (outdata == indata)
- return ACCESS_32;
-
- outdata = 0xC5C0D5D0;
- indata = 0;
-
- /* Write 16 bit output */
- word_memcpy_tocard(membase, &outdata, 4);
- /* Now read it back */
- word_memcpy_fromcard(&indata, membase, 4);
- if (outdata == indata)
- return ACCESS_16;
-
- return ACCESS_UNKNOWN;
-}
-
-static int mac8390_memsize(unsigned long membase)
-{
- unsigned long flags;
- int i, j;
-
- local_irq_save(flags);
- /* Check up to 32K in 4K increments */
- for (i = 0; i < 8; i++) {
- volatile unsigned short *m = (unsigned short *)(membase + (i * 0x1000));
-
- /* Unwriteable - we have a fully decoded card and the
- RAM end located */
- if (hwreg_present(m) == 0)
- break;
-
- /* write a distinctive byte */
- *m = 0xA5A0 | i;
- /* check that we read back what we wrote */
- if (*m != (0xA5A0 | i))
- break;
-
- /* check for partial decode and wrap */
- for (j = 0; j < i; j++) {
- volatile unsigned short *p = (unsigned short *)(membase + (j * 0x1000));
- if (*p != (0xA5A0 | j))
- break;
- }
- }
- local_irq_restore(flags);
- /*
- * in any case, we stopped once we tried one block too many,
- * or once we reached 32K
- */
- return i * 0x1000;
-}
-
-static bool mac8390_rsrc_init(struct net_device *dev,
- struct nubus_rsrc *fres,
- enum mac8390_type cardtype)
-{
- struct nubus_board *board = fres->board;
- struct nubus_dir dir;
- struct nubus_dirent ent;
- int offset;
- volatile unsigned short *i;
- u8 addr[ETH_ALEN];
-
- dev->irq = SLOT2IRQ(board->slot);
- /* This is getting to be a habit */
- dev->base_addr = board->slot_addr | ((board->slot & 0xf) << 20);
-
- /*
- * Get some Nubus info - we will trust the card's idea
- * of where its memory and registers are.
- */
-
- if (nubus_get_func_dir(fres, &dir) == -1) {
- dev_err(&board->dev,
- "Unable to get Nubus functional directory\n");
- return false;
- }
-
- /* Get the MAC address */
- if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) {
- dev_info(&board->dev, "MAC address resource not found\n");
- return false;
- }
-
- nubus_get_rsrc_mem(addr, &ent, 6);
- eth_hw_addr_set(dev, addr);
-
- if (useresources[cardtype] == 1) {
- nubus_rewinddir(&dir);
- if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS,
- &ent) == -1) {
- dev_err(&board->dev,
- "Memory offset resource not found\n");
- return false;
- }
- nubus_get_rsrc_mem(&offset, &ent, 4);
- dev->mem_start = dev->base_addr + offset;
- /* yes, this is how the Apple driver does it */
- dev->base_addr = dev->mem_start + 0x10000;
- nubus_rewinddir(&dir);
- if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH,
- &ent) == -1) {
- dev_info(&board->dev,
- "Memory length resource not found, probing\n");
- offset = mac8390_memsize(dev->mem_start);
- } else {
- nubus_get_rsrc_mem(&offset, &ent, 4);
- }
- dev->mem_end = dev->mem_start + offset;
- } else {
- switch (cardtype) {
- case MAC8390_KINETICS:
- case MAC8390_DAYNA: /* it's the same */
- dev->base_addr = (int)(board->slot_addr +
- DAYNA_8390_BASE);
- dev->mem_start = (int)(board->slot_addr +
- DAYNA_8390_MEM);
- dev->mem_end = dev->mem_start +
- mac8390_memsize(dev->mem_start);
- break;
- case MAC8390_INTERLAN:
- dev->base_addr = (int)(board->slot_addr +
- INTERLAN_8390_BASE);
- dev->mem_start = (int)(board->slot_addr +
- INTERLAN_8390_MEM);
- dev->mem_end = dev->mem_start +
- mac8390_memsize(dev->mem_start);
- break;
- case MAC8390_CABLETRON:
- dev->base_addr = (int)(board->slot_addr +
- CABLETRON_8390_BASE);
- dev->mem_start = (int)(board->slot_addr +
- CABLETRON_8390_MEM);
- /* The base address is unreadable if 0x00
- * has been written to the command register
- * Reset the chip by writing E8390_NODMA +
- * E8390_PAGE0 + E8390_STOP just to be
- * sure
- */
- i = (void *)dev->base_addr;
- *i = 0x21;
- dev->mem_end = dev->mem_start +
- mac8390_memsize(dev->mem_start);
- break;
-
- default:
- dev_err(&board->dev,
- "No known base address for card type\n");
- return false;
- }
- }
-
- return true;
-}
-
-static int mac8390_device_probe(struct nubus_board *board)
-{
- struct net_device *dev;
- int err = -ENODEV;
- struct nubus_rsrc *fres;
- enum mac8390_type cardtype = MAC8390_NONE;
-
- dev = ____alloc_ei_netdev(0);
- if (!dev)
- return -ENOMEM;
-
- SET_NETDEV_DEV(dev, &board->dev);
-
- for_each_board_func_rsrc(board, fres) {
- if (fres->category != NUBUS_CAT_NETWORK ||
- fres->type != NUBUS_TYPE_ETHERNET)
- continue;
-
- cardtype = mac8390_ident(fres);
- if (cardtype == MAC8390_NONE)
- continue;
-
- if (mac8390_rsrc_init(dev, fres, cardtype))
- break;
- }
- if (!fres)
- goto out;
-
- err = mac8390_initdev(dev, board, cardtype);
- if (err)
- goto out;
-
- err = register_netdev(dev);
- if (err)
- goto out;
-
- nubus_set_drvdata(board, dev);
- return 0;
-
-out:
- free_netdev(dev);
- return err;
-}
-
-static void mac8390_device_remove(struct nubus_board *board)
-{
- struct net_device *dev = nubus_get_drvdata(board);
-
- unregister_netdev(dev);
- free_netdev(dev);
-}
-
-static struct nubus_driver mac8390_driver = {
- .probe = mac8390_device_probe,
- .remove = mac8390_device_remove,
- .driver = {
- .name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
- }
-};
-
-MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others");
-MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver");
-MODULE_LICENSE("GPL");
-
-static int __init mac8390_init(void)
-{
- return nubus_driver_register(&mac8390_driver);
-}
-module_init(mac8390_init);
-
-static void __exit mac8390_exit(void)
-{
- nubus_driver_unregister(&mac8390_driver);
-}
-module_exit(mac8390_exit);
-
-static const struct net_device_ops mac8390_netdev_ops = {
- .ndo_open = mac8390_open,
- .ndo_stop = mac8390_close,
- .ndo_start_xmit = __ei_start_xmit,
- .ndo_tx_timeout = __ei_tx_timeout,
- .ndo_get_stats = __ei_get_stats,
- .ndo_set_rx_mode = __ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = __ei_poll,
-#endif
-};
-
-static int mac8390_initdev(struct net_device *dev, struct nubus_board *board,
- enum mac8390_type type)
-{
- static u32 fwrd4_offsets[16] = {
- 0, 4, 8, 12,
- 16, 20, 24, 28,
- 32, 36, 40, 44,
- 48, 52, 56, 60
- };
- static u32 back4_offsets[16] = {
- 60, 56, 52, 48,
- 44, 40, 36, 32,
- 28, 24, 20, 16,
- 12, 8, 4, 0
- };
- static u32 fwrd2_offsets[16] = {
- 0, 2, 4, 6,
- 8, 10, 12, 14,
- 16, 18, 20, 22,
- 24, 26, 28, 30
- };
-
- int access_bitmode = 0;
-
- /* Now fill in our stuff */
- dev->netdev_ops = &mac8390_netdev_ops;
-
- /* GAR, ei_status is actually a macro even though it looks global */
- ei_status.name = cardname[type];
- ei_status.word16 = word16[type];
-
- /* Cabletron's TX/RX buffers are backwards */
- if (type == MAC8390_CABLETRON) {
- ei_status.tx_start_page = CABLETRON_TX_START_PG;
- ei_status.rx_start_page = CABLETRON_RX_START_PG;
- ei_status.stop_page = CABLETRON_RX_STOP_PG;
- ei_status.rmem_start = dev->mem_start;
- ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
- } else {
- ei_status.tx_start_page = WD_START_PG;
- ei_status.rx_start_page = WD_START_PG + TX_PAGES;
- ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
- ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
- ei_status.rmem_end = dev->mem_end;
- }
-
- /* Fill in model-specific information and functions */
- switch (type) {
- case MAC8390_FARALLON:
- case MAC8390_APPLE:
- switch (mac8390_testio(dev->mem_start)) {
- case ACCESS_UNKNOWN:
- dev_err(&board->dev,
- "Don't know how to access card memory\n");
- return -ENODEV;
-
- case ACCESS_16:
- /* 16 bit card, register map is reversed */
- ei_status.reset_8390 = mac8390_no_reset;
- ei_status.block_input = slow_sane_block_input;
- ei_status.block_output = slow_sane_block_output;
- ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
- ei_status.reg_offset = back4_offsets;
- break;
-
- case ACCESS_32:
- /* 32 bit card, register map is reversed */
- ei_status.reset_8390 = mac8390_no_reset;
- ei_status.block_input = sane_block_input;
- ei_status.block_output = sane_block_output;
- ei_status.get_8390_hdr = sane_get_8390_hdr;
- ei_status.reg_offset = back4_offsets;
- access_bitmode = 1;
- break;
- }
- break;
-
- case MAC8390_ASANTE:
- /* Some Asante cards pass the 32 bit test
- * but overwrite system memory when run at 32 bit.
- * so we run them all at 16 bit.
- */
- ei_status.reset_8390 = mac8390_no_reset;
- ei_status.block_input = slow_sane_block_input;
- ei_status.block_output = slow_sane_block_output;
- ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
- ei_status.reg_offset = back4_offsets;
- break;
-
- case MAC8390_CABLETRON:
- /* 16 bit card, register map is short forward */
- ei_status.reset_8390 = mac8390_no_reset;
- ei_status.block_input = slow_sane_block_input;
- ei_status.block_output = slow_sane_block_output;
- ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
- ei_status.reg_offset = fwrd2_offsets;
- break;
-
- case MAC8390_DAYNA:
- case MAC8390_KINETICS:
- /* 16 bit memory, register map is forward */
- /* dayna and similar */
- ei_status.reset_8390 = mac8390_no_reset;
- ei_status.block_input = dayna_block_input;
- ei_status.block_output = dayna_block_output;
- ei_status.get_8390_hdr = dayna_get_8390_hdr;
- ei_status.reg_offset = fwrd4_offsets;
- break;
-
- case MAC8390_INTERLAN:
- /* 16 bit memory, register map is forward */
- ei_status.reset_8390 = interlan_reset;
- ei_status.block_input = slow_sane_block_input;
- ei_status.block_output = slow_sane_block_output;
- ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
- ei_status.reg_offset = fwrd4_offsets;
- break;
-
- default:
- dev_err(&board->dev, "Unsupported card type\n");
- return -ENODEV;
- }
-
- __NS8390_init(dev, 0);
-
- /* Good, done, now spit out some messages */
- dev_info(&board->dev, "%s (type %s)\n", board->name, cardname[type]);
- dev_info(&board->dev, "MAC %pM, IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n",
- dev->dev_addr, dev->irq,
- (unsigned int)(dev->mem_end - dev->mem_start) >> 10,
- dev->mem_start, access_bitmode ? 32 : 16);
- return 0;
-}
-
-static int mac8390_open(struct net_device *dev)
-{
- int err;
-
- __ei_open(dev);
- err = request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev);
- if (err)
- pr_err("%s: unable to get IRQ %d\n", dev->name, dev->irq);
- return err;
-}
-
-static int mac8390_close(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- __ei_close(dev);
- return 0;
-}
-
-static void mac8390_no_reset(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- ei_status.txing = 0;
- netif_info(ei_local, hw, dev, "reset not supported\n");
-}
-
-static void interlan_reset(struct net_device *dev)
-{
- unsigned char *target = nubus_slot_addr(IRQ2SLOT(dev->irq));
- struct ei_device *ei_local = netdev_priv(dev);
-
- netif_info(ei_local, hw, dev, "Need to reset the NS8390 t=%lu...",
- jiffies);
- ei_status.txing = 0;
- target[0xC0000] = 0;
- if (netif_msg_hw(ei_local))
- pr_cont("reset complete\n");
-}
-
-/* dayna_memcpy_fromio/dayna_memcpy_toio */
-/* directly from daynaport.c by Alan Cox */
-static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from,
- int count)
-{
- volatile unsigned char *ptr;
- unsigned char *target = to;
- from <<= 1; /* word, skip overhead */
- ptr = (unsigned char *)(dev->mem_start+from);
- /* Leading byte? */
- if (from & 2) {
- *target++ = ptr[-1];
- ptr += 2;
- count--;
- }
- while (count >= 2) {
- *(unsigned short *)target = *(unsigned short volatile *)ptr;
- ptr += 4; /* skip cruft */
- target += 2;
- count -= 2;
- }
- /* Trailing byte? */
- if (count)
- *target = *ptr;
-}
-
-static void dayna_memcpy_tocard(struct net_device *dev, int to,
- const void *from, int count)
-{
- volatile unsigned short *ptr;
- const unsigned char *src = from;
- to <<= 1; /* word, skip overhead */
- ptr = (unsigned short *)(dev->mem_start+to);
- /* Leading byte? */
- if (to & 2) { /* avoid a byte write (stomps on other data) */
- ptr[-1] = (ptr[-1]&0xFF00)|*src++;
- ptr++;
- count--;
- }
- while (count >= 2) {
- *ptr++ = *(unsigned short *)src; /* Copy and */
- ptr++; /* skip cruft */
- src += 2;
- count -= 2;
- }
- /* Trailing byte? */
- if (count) {
- /* card doesn't like byte writes */
- *ptr = (*ptr & 0x00FF) | (*src << 8);
- }
-}
-
-/* sane block input/output */
-static void sane_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page)
-{
- unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
- memcpy_fromio(hdr, (void __iomem *)dev->mem_start + hdr_start, 4);
- /* Fix endianness */
- hdr->count = swab16(hdr->count);
-}
-
-static void sane_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
- unsigned long xfer_start = xfer_base + dev->mem_start;
-
- if (xfer_start + count > ei_status.rmem_end) {
- /* We must wrap the input move. */
- int semi_count = ei_status.rmem_end - xfer_start;
- memcpy_fromio(skb->data,
- (void __iomem *)dev->mem_start + xfer_base,
- semi_count);
- count -= semi_count;
- memcpy_fromio(skb->data + semi_count,
- (void __iomem *)ei_status.rmem_start, count);
- } else {
- memcpy_fromio(skb->data,
- (void __iomem *)dev->mem_start + xfer_base,
- count);
- }
-}
-
-static void sane_block_output(struct net_device *dev, int count,
- const unsigned char *buf, int start_page)
-{
- long shmem = (start_page - WD_START_PG)<<8;
-
- memcpy_toio((void __iomem *)dev->mem_start + shmem, buf, count);
-}
-
-/* dayna block input/output */
-static void dayna_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page)
-{
- unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
-
- dayna_memcpy_fromcard(dev, hdr, hdr_start, 4);
- /* Fix endianness */
- hdr->count = (hdr->count & 0xFF) << 8 | (hdr->count >> 8);
-}
-
-static void dayna_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
- unsigned long xfer_start = xfer_base+dev->mem_start;
-
- /* Note the offset math is done in card memory space which is word
- per long onto our space. */
-
- if (xfer_start + count > ei_status.rmem_end) {
- /* We must wrap the input move. */
- int semi_count = ei_status.rmem_end - xfer_start;
- dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
- count -= semi_count;
- dayna_memcpy_fromcard(dev, skb->data + semi_count,
- ei_status.rmem_start - dev->mem_start,
- count);
- } else {
- dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
- }
-}
-
-static void dayna_block_output(struct net_device *dev, int count,
- const unsigned char *buf,
- int start_page)
-{
- long shmem = (start_page - WD_START_PG)<<8;
-
- dayna_memcpy_tocard(dev, shmem, buf, count);
-}
-
-/* Cabletron block I/O */
-static void slow_sane_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr,
- int ring_page)
-{
- unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
- word_memcpy_fromcard(hdr, dev->mem_start + hdr_start, 4);
- /* Register endianism - fix here rather than 8390.c */
- hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8);
-}
-
-static void slow_sane_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
- unsigned long xfer_start = xfer_base+dev->mem_start;
-
- if (xfer_start + count > ei_status.rmem_end) {
- /* We must wrap the input move. */
- int semi_count = ei_status.rmem_end - xfer_start;
- word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
- semi_count);
- count -= semi_count;
- word_memcpy_fromcard(skb->data + semi_count,
- ei_status.rmem_start, count);
- } else {
- word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
- count);
- }
-}
-
-static void slow_sane_block_output(struct net_device *dev, int count,
- const unsigned char *buf, int start_page)
-{
- long shmem = (start_page - WD_START_PG)<<8;
-
- word_memcpy_tocard(dev->mem_start + shmem, buf, count);
-}
-
-static void word_memcpy_tocard(unsigned long tp, const void *fp, int count)
-{
- volatile unsigned short *to = (void *)tp;
- const unsigned short *from = fp;
-
- count++;
- count /= 2;
-
- while (count--)
- *to++ = *from++;
-}
-
-static void word_memcpy_fromcard(void *tp, unsigned long fp, int count)
-{
- unsigned short *to = tp;
- const volatile unsigned short *from = (const void *)fp;
-
- count++;
- count /= 2;
-
- while (count--)
- *to++ = *from++;
-}
-
-
diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c
deleted file mode 100644
index 94ff8364c..000000000
--- a/drivers/net/ethernet/8390/mcf8390.c
+++ /dev/null
@@ -1,468 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Support for ColdFire CPU based boards using a NS8390 Ethernet device.
- *
- * Derived from the many other 8390 drivers.
- *
- * (C) Copyright 2012, Greg Ungerer <gerg@uclinux.org>
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/jiffies.h>
-#include <linux/io.h>
-#include <asm/mcf8390.h>
-
-static const char version[] =
- "mcf8390.c: (15-06-2012) Greg Ungerer <gerg@uclinux.org>";
-
-#define NE_CMD 0x00
-#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset */
-#define NE_RESET 0x1f /* Issue a read to reset ,a write to clear */
-#define NE_EN0_ISR 0x07
-#define NE_EN0_DCFG 0x0e
-#define NE_EN0_RSARLO 0x08
-#define NE_EN0_RSARHI 0x09
-#define NE_EN0_RCNTLO 0x0a
-#define NE_EN0_RXCR 0x0c
-#define NE_EN0_TXCR 0x0d
-#define NE_EN0_RCNTHI 0x0b
-#define NE_EN0_IMR 0x0f
-
-#define NESM_START_PG 0x40 /* First page of TX buffer */
-#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-#ifdef NE2000_ODDOFFSET
-/*
- * A lot of the ColdFire boards use a separate address region for odd offset
- * register addresses. The following functions convert and map as required.
- * Note that the data port accesses are treated a little differently, and
- * always accessed via the insX/outsX functions.
- */
-static inline u32 NE_PTR(u32 addr)
-{
- if (addr & 1)
- return addr - 1 + NE2000_ODDOFFSET;
- return addr;
-}
-
-static inline u32 NE_DATA_PTR(u32 addr)
-{
- return addr;
-}
-
-void ei_outb(u32 val, u32 addr)
-{
- NE2000_BYTE *rp;
-
- rp = (NE2000_BYTE *) NE_PTR(addr);
- *rp = RSWAP(val);
-}
-
-#define ei_inb ei_inb
-u8 ei_inb(u32 addr)
-{
- NE2000_BYTE *rp, val;
-
- rp = (NE2000_BYTE *) NE_PTR(addr);
- val = *rp;
- return (u8) (RSWAP(val) & 0xff);
-}
-
-void ei_insb(u32 addr, void *vbuf, int len)
-{
- NE2000_BYTE *rp, val;
- u8 *buf;
-
- buf = (u8 *) vbuf;
- rp = (NE2000_BYTE *) NE_DATA_PTR(addr);
- for (; (len > 0); len--) {
- val = *rp;
- *buf++ = RSWAP(val);
- }
-}
-
-void ei_insw(u32 addr, void *vbuf, int len)
-{
- volatile u16 *rp;
- u16 w, *buf;
-
- buf = (u16 *) vbuf;
- rp = (volatile u16 *) NE_DATA_PTR(addr);
- for (; (len > 0); len--) {
- w = *rp;
- *buf++ = BSWAP(w);
- }
-}
-
-void ei_outsb(u32 addr, const void *vbuf, int len)
-{
- NE2000_BYTE *rp, val;
- u8 *buf;
-
- buf = (u8 *) vbuf;
- rp = (NE2000_BYTE *) NE_DATA_PTR(addr);
- for (; (len > 0); len--) {
- val = *buf++;
- *rp = RSWAP(val);
- }
-}
-
-void ei_outsw(u32 addr, const void *vbuf, int len)
-{
- volatile u16 *rp;
- u16 w, *buf;
-
- buf = (u16 *) vbuf;
- rp = (volatile u16 *) NE_DATA_PTR(addr);
- for (; (len > 0); len--) {
- w = *buf++;
- *rp = BSWAP(w);
- }
-}
-
-#else /* !NE2000_ODDOFFSET */
-
-#define ei_inb inb
-#define ei_outb outb
-#define ei_insb insb
-#define ei_insw insw
-#define ei_outsb outsb
-#define ei_outsw outsw
-
-#endif /* !NE2000_ODDOFFSET */
-
-#define ei_inb_p ei_inb
-#define ei_outb_p ei_outb
-
-#include "lib8390.c"
-
-/*
- * Hard reset the card. This used to pause for the same period that a
- * 8390 reset command required, but that shouldn't be necessary.
- */
-static void mcf8390_reset_8390(struct net_device *dev)
-{
- unsigned long reset_start_time = jiffies;
- u32 addr = dev->base_addr;
- struct ei_device *ei_local = netdev_priv(dev);
-
- netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
-
- ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
-
- ei_status.txing = 0;
- ei_status.dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RESET) == 0) {
- if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
- netdev_warn(dev, "%s: did not complete\n", __func__);
- break;
- }
- }
-
- ei_outb(ENISR_RESET, addr + NE_EN0_ISR);
-}
-
-/*
- * This *shouldn't* happen.
- * If it does, it's the last thing you'll see
- */
-static void mcf8390_dmaing_err(const char *func, struct net_device *dev,
- struct ei_device *ei_local)
-{
- netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
- func, ei_local->dmaing, ei_local->irqlock);
-}
-
-/*
- * Grab the 8390 specific header. Similar to the block_input routine, but
- * we don't need to be concerned with ring wrap as the header will be at
- * the start of a page, so we optimize accordingly.
- */
-static void mcf8390_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- u32 addr = dev->base_addr;
-
- if (ei_local->dmaing) {
- mcf8390_dmaing_err(__func__, dev, ei_local);
- return;
- }
-
- ei_local->dmaing |= 0x01;
- ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, addr + NE_CMD);
- ei_outb(ENISR_RDC, addr + NE_EN0_ISR);
- ei_outb(sizeof(struct e8390_pkt_hdr), addr + NE_EN0_RCNTLO);
- ei_outb(0, addr + NE_EN0_RCNTHI);
- ei_outb(0, addr + NE_EN0_RSARLO); /* On page boundary */
- ei_outb(ring_page, addr + NE_EN0_RSARHI);
- ei_outb(E8390_RREAD + E8390_START, addr + NE_CMD);
-
- ei_insw(addr + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr) >> 1);
-
- outb(ENISR_RDC, addr + NE_EN0_ISR); /* Ack intr */
- ei_local->dmaing &= ~0x01;
-
- hdr->count = cpu_to_le16(hdr->count);
-}
-
-/*
- * Block input and output, similar to the Crynwr packet driver.
- * If you are porting to a new ethercard, look at the packet driver source
- * for hints. The NEx000 doesn't share the on-board packet memory --
- * you have to put the packet out through the "remote DMA" dataport
- * using z_writeb.
- */
-static void mcf8390_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- u32 addr = dev->base_addr;
- char *buf = skb->data;
-
- if (ei_local->dmaing) {
- mcf8390_dmaing_err(__func__, dev, ei_local);
- return;
- }
-
- ei_local->dmaing |= 0x01;
- ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, addr + NE_CMD);
- ei_outb(ENISR_RDC, addr + NE_EN0_ISR);
- ei_outb(count & 0xff, addr + NE_EN0_RCNTLO);
- ei_outb(count >> 8, addr + NE_EN0_RCNTHI);
- ei_outb(ring_offset & 0xff, addr + NE_EN0_RSARLO);
- ei_outb(ring_offset >> 8, addr + NE_EN0_RSARHI);
- ei_outb(E8390_RREAD + E8390_START, addr + NE_CMD);
-
- ei_insw(addr + NE_DATAPORT, buf, count >> 1);
- if (count & 1)
- buf[count - 1] = ei_inb(addr + NE_DATAPORT);
-
- ei_outb(ENISR_RDC, addr + NE_EN0_ISR); /* Ack intr */
- ei_local->dmaing &= ~0x01;
-}
-
-static void mcf8390_block_output(struct net_device *dev, int count,
- const unsigned char *buf,
- const int start_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- u32 addr = dev->base_addr;
- unsigned long dma_start;
-
- /* Make sure we transfer all bytes if 16bit IO writes */
- if (count & 0x1)
- count++;
-
- if (ei_local->dmaing) {
- mcf8390_dmaing_err(__func__, dev, ei_local);
- return;
- }
-
- ei_local->dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- ei_outb(E8390_PAGE0 + E8390_START + E8390_NODMA, addr + NE_CMD);
-
- ei_outb(ENISR_RDC, addr + NE_EN0_ISR);
-
- /* Now the normal output. */
- ei_outb(count & 0xff, addr + NE_EN0_RCNTLO);
- ei_outb(count >> 8, addr + NE_EN0_RCNTHI);
- ei_outb(0x00, addr + NE_EN0_RSARLO);
- ei_outb(start_page, addr + NE_EN0_RSARHI);
- ei_outb(E8390_RWRITE + E8390_START, addr + NE_CMD);
-
- ei_outsw(addr + NE_DATAPORT, buf, count >> 1);
-
- dma_start = jiffies;
- while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RDC) == 0) {
- if (time_after(jiffies, dma_start + 2 * HZ / 100)) { /* 20ms */
- netdev_warn(dev, "timeout waiting for Tx RDC\n");
- mcf8390_reset_8390(dev);
- __NS8390_init(dev, 1);
- break;
- }
- }
-
- ei_outb(ENISR_RDC, addr + NE_EN0_ISR); /* Ack intr */
- ei_local->dmaing &= ~0x01;
-}
-
-static const struct net_device_ops mcf8390_netdev_ops = {
- .ndo_open = __ei_open,
- .ndo_stop = __ei_close,
- .ndo_start_xmit = __ei_start_xmit,
- .ndo_tx_timeout = __ei_tx_timeout,
- .ndo_get_stats = __ei_get_stats,
- .ndo_set_rx_mode = __ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = __ei_poll,
-#endif
-};
-
-static int mcf8390_init(struct net_device *dev)
-{
- static u32 offsets[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- };
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned char SA_prom[32];
- u32 addr = dev->base_addr;
- int start_page, stop_page;
- int i, ret;
-
- mcf8390_reset_8390(dev);
-
- /*
- * Read the 16 bytes of station address PROM.
- * We must first initialize registers,
- * similar to NS8390_init(eifdev, 0).
- * We can't reliably read the SAPROM address without this.
- * (I learned the hard way!).
- */
- {
- static const struct {
- u32 value;
- u32 offset;
- } program_seq[] = {
- {E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
- /* Select page 0 */
- {0x48, NE_EN0_DCFG}, /* 0x48: Set byte-wide access */
- {0x00, NE_EN0_RCNTLO}, /* Clear the count regs */
- {0x00, NE_EN0_RCNTHI},
- {0x00, NE_EN0_IMR}, /* Mask completion irq */
- {0xFF, NE_EN0_ISR},
- {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
- {32, NE_EN0_RCNTLO},
- {0x00, NE_EN0_RCNTHI},
- {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000 */
- {0x00, NE_EN0_RSARHI},
- {E8390_RREAD + E8390_START, NE_CMD},
- };
- for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
- ei_outb(program_seq[i].value,
- addr + program_seq[i].offset);
- }
- }
-
- for (i = 0; i < 16; i++) {
- SA_prom[i] = ei_inb(addr + NE_DATAPORT);
- ei_inb(addr + NE_DATAPORT);
- }
-
- /* We must set the 8390 for word mode. */
- ei_outb(0x49, addr + NE_EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
-
- /* Install the Interrupt handler */
- ret = request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev);
- if (ret)
- return ret;
-
- eth_hw_addr_set(dev, SA_prom);
-
- netdev_dbg(dev, "Found ethernet address: %pM\n", dev->dev_addr);
-
- ei_local->name = "mcf8390";
- ei_local->tx_start_page = start_page;
- ei_local->stop_page = stop_page;
- ei_local->word16 = 1;
- ei_local->rx_start_page = start_page + TX_PAGES;
- ei_local->reset_8390 = mcf8390_reset_8390;
- ei_local->block_input = mcf8390_block_input;
- ei_local->block_output = mcf8390_block_output;
- ei_local->get_8390_hdr = mcf8390_get_8390_hdr;
- ei_local->reg_offset = offsets;
-
- dev->netdev_ops = &mcf8390_netdev_ops;
- __NS8390_init(dev, 0);
- ret = register_netdev(dev);
- if (ret) {
- free_irq(dev->irq, dev);
- return ret;
- }
-
- netdev_info(dev, "addr=0x%08x irq=%d, Ethernet Address %pM\n",
- addr, dev->irq, dev->dev_addr);
- return 0;
-}
-
-static int mcf8390_probe(struct platform_device *pdev)
-{
- struct net_device *dev;
- struct resource *mem;
- resource_size_t msize;
- int ret, irq;
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return -ENXIO;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (mem == NULL) {
- dev_err(&pdev->dev, "no memory address specified?\n");
- return -ENXIO;
- }
- msize = resource_size(mem);
- if (!request_mem_region(mem->start, msize, pdev->name))
- return -EBUSY;
-
- dev = ____alloc_ei_netdev(0);
- if (dev == NULL) {
- release_mem_region(mem->start, msize);
- return -ENOMEM;
- }
-
- SET_NETDEV_DEV(dev, &pdev->dev);
- platform_set_drvdata(pdev, dev);
-
- dev->irq = irq;
- dev->base_addr = mem->start;
-
- ret = mcf8390_init(dev);
- if (ret) {
- release_mem_region(mem->start, msize);
- free_netdev(dev);
- return ret;
- }
- return 0;
-}
-
-static void mcf8390_remove(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct resource *mem;
-
- unregister_netdev(dev);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
- free_netdev(dev);
-}
-
-static struct platform_driver mcf8390_drv = {
- .driver = {
- .name = "mcf8390",
- },
- .probe = mcf8390_probe,
- .remove = mcf8390_remove,
-};
-
-module_platform_driver(mcf8390_drv);
-
-MODULE_DESCRIPTION("MCF8390 ColdFire NS8390 driver");
-MODULE_AUTHOR("Greg Ungerer <gerg@uclinux.org>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:mcf8390");
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
deleted file mode 100644
index 961019c32..000000000
--- a/drivers/net/ethernet/8390/ne.c
+++ /dev/null
@@ -1,992 +0,0 @@
-// SPDX-License-Identifier: GPL-1.0+
-/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
-/*
- Written 1992-94 by Donald Becker.
-
- Copyright 1993 United States Government as represented by the
- Director, National Security Agency.
-
- The author may be reached as becker@scyld.com, or C/O
- Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
-
- This driver should work with many programmed-I/O 8390-based ethernet
- boards. Currently it supports the NE1000, NE2000, many clones,
- and some Cabletron products.
-
- Changelog:
-
- Paul Gortmaker : use ENISR_RDC to monitor Tx PIO uploads, made
- sanity checks and bad clone support optional.
- Paul Gortmaker : new reset code, reset card after probe at boot.
- Paul Gortmaker : multiple card support for module users.
- Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c
- Paul Gortmaker : Allow users with bad cards to avoid full probe.
- Paul Gortmaker : PCI probe changes, more PCI cards supported.
- rjohnson@analogic.com : Changed init order so an interrupt will only
- occur after memory is allocated for dev->priv. Deallocated memory
- last in cleanup_modue()
- Richard Guenther : Added support for ISAPnP cards
- Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead.
- Hayato Fujiwara : Add m32r support.
-
-*/
-
-/* Routines for the NatSemi-based designs (NE[12]000). */
-
-static const char version1[] =
-"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n";
-static const char version2[] =
-"Last modified Nov 1, 2000 by Paul Gortmaker\n";
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/isapnp.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/jiffies.h>
-#include <linux/platform_device.h>
-#include <net/Space.h>
-
-#include <asm/io.h>
-
-#include "8390.h"
-
-#define DRV_NAME "ne"
-
-/* Some defines that people can play with if so inclined. */
-
-/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
-#define SUPPORT_NE_BAD_CLONES
-/* 0xbad = bad sig or no reset ack */
-#define BAD 0xbad
-
-#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
-static struct platform_device *pdev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS];
-static u32 ne_msg_enable;
-
-#ifdef MODULE
-module_param_hw_array(io, int, ioport, NULL, 0);
-module_param_hw_array(irq, int, irq, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-module_param_named(msg_enable, ne_msg_enable, uint, 0444);
-MODULE_PARM_DESC(io, "I/O base address(es),required");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
-MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
-MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
-MODULE_LICENSE("GPL");
-#endif /* MODULE */
-
-/* Do we perform extra sanity checks on stuff ? */
-/* #define NE_SANITY_CHECK */
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
-/* #define PACKETBUF_MEMSIZE 0x40 */
-
-/* This is set up so that no ISA autoprobe takes place. We can't guarantee
-that the ne2k probe is the last 8390 based probe to take place (as it
-is at boot) and so the probe will get confused by any other 8390 cards.
-ISA device autoprobes on a running machine are not recommended anyway. */
-#if !defined(MODULE) && defined(CONFIG_ISA)
-/* Do we need a portlist for the ISA auto-probe ? */
-#define NEEDS_PORTLIST
-#endif
-
-/* A zero-terminated list of I/O addresses to be probed at boot. */
-#ifdef NEEDS_PORTLIST
-static unsigned int netcard_portlist[] __initdata = {
- 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
-};
-#endif
-
-static struct isapnp_device_id isapnp_clone_list[] __initdata = {
- { ISAPNP_CARD_ID('A','X','E',0x2011),
- ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
- (long) "NetGear EA201" },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
- (long) "NN NE2000" },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
- (long) "Generic PNP" },
- { } /* terminate list */
-};
-
-MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
-
-#ifdef SUPPORT_NE_BAD_CLONES
-/* A list of bad clones that we none-the-less recognize. */
-static struct { const char *name8, *name16; unsigned char SAprefix[4];}
-bad_clone_list[] __initdata = {
- {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
- {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
- {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh? */
- {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
- {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
- {"NN1000", "NN2000", {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
- {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}}, /* Outlaw 4-Dimension cards. */
- {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
- {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
- {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
- {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
- {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
- {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
-#ifdef CONFIG_MACH_TX49XX
- {"RBHMA4X00-RTL8019", "RBHMA4X00-RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */
-#endif
- {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
- {NULL,}
-};
-#endif
-
-/* ---- No user-serviceable parts below ---- */
-
-#define NE_BASE (dev->base_addr)
-#define NE_CMD 0x00
-#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
-#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT 0x20
-
-#define NE1SM_START_PG 0x20 /* First page of TX buffer */
-#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
-#define NESM_START_PG 0x40 /* First page of TX buffer */
-#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-#if defined(CONFIG_MACH_TX49XX)
-# define DCR_VAL 0x48 /* 8-bit mode */
-#elif defined(CONFIG_ATARI) /* 8-bit mode on Atari, normal on Q40 */
-# define DCR_VAL (MACH_IS_ATARI ? 0x48 : 0x49)
-#else
-# define DCR_VAL 0x49
-#endif
-
-static int ne_probe1(struct net_device *dev, unsigned long ioaddr);
-static int ne_probe_isapnp(struct net_device *dev);
-
-static void ne_reset_8390(struct net_device *dev);
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
- int ring_page);
-static void ne_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct net_device *dev, const int count,
- const unsigned char *buf, const int start_page);
-
-
-/* Probe for various non-shared-memory ethercards.
-
- NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
- buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
- the SAPROM, while other supposed NE2000 clones must be detected by their
- SA prefix.
-
- Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
- mode results in doubled values, which can be detected and compensated for.
-
- The probe is also responsible for initializing the card and filling
- in the 'dev' and 'ei_status' structures.
-
- We use the minimum memory size for some ethercard product lines, iff we can't
- distinguish models. You can increase the packet buffer size by setting
- PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are:
- E1010 starts at 0x100 and ends at 0x2000.
- E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
- E2010 starts at 0x100 and ends at 0x4000.
- E2010-x starts at 0x100 and ends at 0xffff. */
-
-static int __init do_ne_probe(struct net_device *dev)
-{
- unsigned long base_addr = dev->base_addr;
-#ifdef NEEDS_PORTLIST
- int orig_irq = dev->irq;
-#endif
-
- /* First check any supplied i/o locations. User knows best. <cough> */
- if (base_addr > 0x1ff) { /* Check a single specified location. */
- int ret = ne_probe1(dev, base_addr);
- if (ret)
- netdev_warn(dev, "ne.c: No NE*000 card found at "
- "i/o = %#lx\n", base_addr);
- return ret;
- }
- else if (base_addr != 0) /* Don't probe at all. */
- return -ENXIO;
-
- /* Then look for any installed ISAPnP clones */
- if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
- return 0;
-
-#ifdef NEEDS_PORTLIST
- /* Last resort. The semi-risky ISA auto-probe. */
- for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
- int ioaddr = netcard_portlist[base_addr];
- dev->irq = orig_irq;
- if (ne_probe1(dev, ioaddr) == 0)
- return 0;
- }
-#endif
-
- return -ENODEV;
-}
-
-static int __init ne_probe_isapnp(struct net_device *dev)
-{
- int i;
-
- for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
- struct pnp_dev *idev = NULL;
-
- while ((idev = pnp_find_dev(NULL,
- isapnp_clone_list[i].vendor,
- isapnp_clone_list[i].function,
- idev))) {
- /* Avoid already found cards from previous calls */
- if (pnp_device_attach(idev) < 0)
- continue;
- if (pnp_activate_dev(idev) < 0) {
- pnp_device_detach(idev);
- continue;
- }
- /* if no io and irq, search for next */
- if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
- pnp_device_detach(idev);
- continue;
- }
- /* found it */
- dev->base_addr = pnp_port_start(idev, 0);
- dev->irq = pnp_irq(idev, 0);
- netdev_info(dev,
- "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
- (char *) isapnp_clone_list[i].driver_data,
- dev->base_addr, dev->irq);
- if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */
- netdev_err(dev,
- "ne.c: Probe of ISAPnP card at %#lx failed.\n",
- dev->base_addr);
- pnp_device_detach(idev);
- return -ENXIO;
- }
- ei_status.priv = (unsigned long)idev;
- break;
- }
- if (!idev)
- continue;
- return 0;
- }
-
- return -ENODEV;
-}
-
-static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
-{
- int i;
- unsigned char SA_prom[32];
- int wordlength = 2;
- const char *name = NULL;
- int start_page, stop_page;
- int neX000, ctron, copam, bad_card;
- int reg0, ret;
- static unsigned version_printed;
- struct ei_device *ei_local = netdev_priv(dev);
-
- if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
- return -EBUSY;
-
- reg0 = inb_p(ioaddr);
- if (reg0 == 0xFF) {
- ret = -ENODEV;
- goto err_out;
- }
-
- /* Do a preliminary verification that we have a 8390. */
- {
- int regd;
- outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
- regd = inb_p(ioaddr + 0x0d);
- outb_p(0xff, ioaddr + 0x0d);
- outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
- inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
- if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
- outb_p(reg0, ioaddr);
- outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */
- ret = -ENODEV;
- goto err_out;
- }
- }
-
- if ((ne_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
- netdev_info(dev, "%s%s", version1, version2);
-
- netdev_info(dev, "NE*000 ethercard probe at %#3lx:", ioaddr);
-
- /* A user with a poor card that fails to ack the reset, or that
- does not have a valid 0x57,0x57 signature can still use this
- without having to recompile. Specifying an i/o address along
- with an otherwise unused dev->mem_end value of "0xBAD" will
- cause the driver to skip these parts of the probe. */
-
- bad_card = ((dev->base_addr != 0) && (dev->mem_end == BAD));
-
- /* Reset card. Who knows what dain-bramaged state it was left in. */
-
- {
- unsigned long reset_start_time = jiffies;
-
- /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
- outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
- while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- if (bad_card) {
- pr_cont(" (warning: no reset ack)");
- break;
- } else {
- pr_cont(" not found (no reset ack).\n");
- ret = -ENODEV;
- goto err_out;
- }
- }
-
- outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */
- }
-
- /* Read the 16 bytes of station address PROM.
- We must first initialize registers, similar to NS8390p_init(eifdev, 0).
- We can't reliably read the SAPROM address without this.
- (I learned the hard way!). */
- {
- struct {unsigned char value, offset; } program_seq[] =
- {
- {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
- {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
- {0x00, EN0_RCNTLO}, /* Clear the count regs. */
- {0x00, EN0_RCNTHI},
- {0x00, EN0_IMR}, /* Mask completion irq. */
- {0xFF, EN0_ISR},
- {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
- {32, EN0_RCNTLO},
- {0x00, EN0_RCNTHI},
- {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
- {0x00, EN0_RSARHI},
- {E8390_RREAD+E8390_START, E8390_CMD},
- };
-
- for (i = 0; i < ARRAY_SIZE(program_seq); i++)
- outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
- }
- for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
- SA_prom[i] = inb(ioaddr + NE_DATAPORT);
- SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
- if (SA_prom[i] != SA_prom[i+1])
- wordlength = 1;
- }
-
- if (wordlength == 2)
- {
- for (i = 0; i < 16; i++)
- SA_prom[i] = SA_prom[i+i];
- /* We must set the 8390 for word mode. */
- outb_p(DCR_VAL, ioaddr + EN0_DCFG);
- start_page = NESM_START_PG;
-
- /*
- * Realtek RTL8019AS datasheet says that the PSTOP register
- * shouldn't exceed 0x60 in 8-bit mode.
- * This chip can be identified by reading the signature from
- * the remote byte count registers (otherwise write-only)...
- */
- if ((DCR_VAL & 0x01) == 0 && /* 8-bit mode */
- inb(ioaddr + EN0_RCNTLO) == 0x50 &&
- inb(ioaddr + EN0_RCNTHI) == 0x70)
- stop_page = 0x60;
- else
- stop_page = NESM_STOP_PG;
- } else {
- start_page = NE1SM_START_PG;
- stop_page = NE1SM_STOP_PG;
- }
-
- neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
- ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
- copam = (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
-
- /* Set up the rest of the parameters. */
- if (neX000 || bad_card || copam) {
- name = (wordlength == 2) ? "NE2000" : "NE1000";
- }
- else if (ctron)
- {
- name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
- start_page = 0x01;
- stop_page = (wordlength == 2) ? 0x40 : 0x20;
- }
- else
- {
-#ifdef SUPPORT_NE_BAD_CLONES
- /* Ack! Well, there might be a *bad* NE*000 clone there.
- Check for total bogus addresses. */
- for (i = 0; bad_clone_list[i].name8; i++)
- {
- if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
- SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
- SA_prom[2] == bad_clone_list[i].SAprefix[2])
- {
- if (wordlength == 2)
- {
- name = bad_clone_list[i].name16;
- } else {
- name = bad_clone_list[i].name8;
- }
- break;
- }
- }
- if (bad_clone_list[i].name8 == NULL)
- {
- pr_cont(" not found (invalid signature %2.2x %2.2x).\n",
- SA_prom[14], SA_prom[15]);
- ret = -ENXIO;
- goto err_out;
- }
-#else
- pr_cont(" not found.\n");
- ret = -ENXIO;
- goto err_out;
-#endif
- }
-
- if (dev->irq < 2)
- {
- unsigned long cookie = probe_irq_on();
- outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
- outb_p(0x00, ioaddr + EN0_RCNTLO);
- outb_p(0x00, ioaddr + EN0_RCNTHI);
- outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
- mdelay(10); /* wait 10ms for interrupt to propagate */
- outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */
- dev->irq = probe_irq_off(cookie);
- if (ne_msg_enable & NETIF_MSG_PROBE)
- pr_cont(" autoirq is %d", dev->irq);
- } else if (dev->irq == 2)
- /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
- or don't know which one to set. */
- dev->irq = 9;
-
- if (! dev->irq) {
- pr_cont(" failed to detect IRQ line.\n");
- ret = -EAGAIN;
- goto err_out;
- }
-
- /* Snarf the interrupt now. There's no point in waiting since we cannot
- share and the board will usually be enabled. */
- ret = request_irq(dev->irq, eip_interrupt, 0, name, dev);
- if (ret) {
- pr_cont(" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
- goto err_out;
- }
-
- dev->base_addr = ioaddr;
-
- eth_hw_addr_set(dev, SA_prom);
-
- pr_cont("%pM\n", dev->dev_addr);
-
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
-
- /* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
- ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
-
- ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
- /* Allow the packet buffer size to be overridden by know-it-alls. */
- ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
- ei_status.reset_8390 = &ne_reset_8390;
- ei_status.block_input = &ne_block_input;
- ei_status.block_output = &ne_block_output;
- ei_status.get_8390_hdr = &ne_get_8390_hdr;
- ei_status.priv = 0;
-
- dev->netdev_ops = &eip_netdev_ops;
- NS8390p_init(dev, 0);
-
- ei_local->msg_enable = ne_msg_enable;
- ret = register_netdev(dev);
- if (ret)
- goto out_irq;
- netdev_info(dev, "%s found at %#lx, using IRQ %d.\n",
- name, ioaddr, dev->irq);
- return 0;
-
-out_irq:
- free_irq(dev->irq, dev);
-err_out:
- release_region(ioaddr, NE_IO_EXTENT);
- return ret;
-}
-
-/* Hard reset the card. This used to pause for the same period that a
- 8390 reset command required, but that shouldn't be necessary. */
-
-static void ne_reset_8390(struct net_device *dev)
-{
- unsigned long reset_start_time = jiffies;
- struct ei_device *ei_local = netdev_priv(dev);
-
- netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
-
- /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
- outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
- ei_status.txing = 0;
- ei_status.dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- netdev_err(dev, "ne_reset_8390() did not complete.\n");
- break;
- }
- outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- we don't need to be concerned with ring wrap as the header will be at
- the start of a page, so we optimize accordingly. */
-
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
- int nic_base = dev->base_addr;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-
- if (ei_status.dmaing)
- {
- netdev_err(dev, "DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d].\n",
- ei_status.dmaing, ei_status.irqlock);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
- outb_p(0, nic_base + EN0_RCNTHI);
- outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
- outb_p(ring_page, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- if (ei_status.word16)
- insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
- else
- insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-
- le16_to_cpus(&hdr->count);
-}
-
-/* Block input and output, similar to the Crynwr packet driver. If you
- are porting to a new ethercard, look at the packet driver source for hints.
- The NEx000 doesn't share the on-board packet memory -- you have to put
- the packet out through the "remote DMA" dataport using outb. */
-
-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-#ifdef NE_SANITY_CHECK
- int xfer_count = count;
- struct ei_device *ei_local = netdev_priv(dev);
-#endif
- int nic_base = dev->base_addr;
- char *buf = skb->data;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing)
- {
- netdev_err(dev, "DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d].\n",
- ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
- outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16)
- {
- insw(NE_BASE + NE_DATAPORT,buf,count>>1);
- if (count & 0x01)
- {
- buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
- xfer_count++;
-#endif
- }
- } else {
- insb(NE_BASE + NE_DATAPORT, buf, count);
- }
-
-#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. If you see
- this message you either 1) have a slightly incompatible clone
- or 2) have noise/speed problems with your bus. */
-
- if (netif_msg_rx_status(ei_local))
- {
- /* DMA termination address check... */
- int addr, tries = 20;
- do {
- /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
- -- it's broken for Rx on some cards! */
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if (((ring_offset + xfer_count) & 0xff) == low)
- break;
- } while (--tries > 0);
- if (tries <= 0)
- netdev_warn(dev, "RX transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- ring_offset + xfer_count, addr);
- }
-#endif
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-static void ne_block_output(struct net_device *dev, int count,
- const unsigned char *buf, const int start_page)
-{
- int nic_base = NE_BASE;
- unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
- int retries = 0;
- struct ei_device *ei_local = netdev_priv(dev);
-#endif
-
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
-
- if (ei_status.word16 && (count & 0x01))
- count++;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing)
- {
- netdev_err(dev, "DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d]\n",
- ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
-
-#ifdef NE_RW_BUGFIX
- /* Handle the read-before-write bug the same way as the
- Crynwr packet driver -- the NatSemi method doesn't work.
- Actually this doesn't always work either, but if you have
- problems with your NEx000 this is better than nothing! */
-
- outb_p(0x42, nic_base + EN0_RCNTLO);
- outb_p(0x00, nic_base + EN0_RCNTHI);
- outb_p(0x42, nic_base + EN0_RSARLO);
- outb_p(0x00, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- /* Make certain that the dummy read has occurred. */
- udelay(6);
-#endif
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR);
-
- /* Now the normal output. */
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(0x00, nic_base + EN0_RSARLO);
- outb_p(start_page, nic_base + EN0_RSARHI);
-
- outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16) {
- outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
- } else {
- outsb(NE_BASE + NE_DATAPORT, buf, count);
- }
-
- dma_start = jiffies;
-
-#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. */
-
- if (netif_msg_tx_queued(ei_local))
- {
- /* DMA termination address check... */
- int addr, tries = 20;
- do {
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if ((start_page << 8) + count == addr)
- break;
- } while (--tries > 0);
-
- if (tries <= 0)
- {
- netdev_warn(dev, "Tx packet transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- (start_page << 8) + count, addr);
- if (retries++ == 0)
- goto retry;
- }
- }
-#endif
-
- while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
- netdev_warn(dev, "timeout waiting for Tx RDC.\n");
- ne_reset_8390(dev);
- NS8390p_init(dev, 1);
- break;
- }
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-static int __init ne_drv_probe(struct platform_device *pdev)
-{
- struct net_device *dev;
- int err, this_dev = pdev->id;
- struct resource *res;
-
- dev = alloc_eip_netdev();
- if (!dev)
- return -ENOMEM;
-
- /* ne.c doesn't populate resources in platform_device, but
- * rbtx4927_ne_init and rbtx4938_ne_init do register devices
- * with resources.
- */
- res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (res) {
- dev->base_addr = res->start;
- dev->irq = platform_get_irq(pdev, 0);
- } else {
- if (this_dev < 0 || this_dev >= MAX_NE_CARDS) {
- free_netdev(dev);
- return -EINVAL;
- }
- dev->base_addr = io[this_dev];
- dev->irq = irq[this_dev];
- dev->mem_end = bad[this_dev];
- }
- SET_NETDEV_DEV(dev, &pdev->dev);
- err = do_ne_probe(dev);
- if (err) {
- free_netdev(dev);
- return err;
- }
- platform_set_drvdata(pdev, dev);
-
- /* Update with any values found by probing, don't update if
- * resources were specified.
- */
- if (!res) {
- io[this_dev] = dev->base_addr;
- irq[this_dev] = dev->irq;
- }
- return 0;
-}
-
-static void ne_drv_remove(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
-
- if (dev) {
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- netif_device_detach(dev);
- unregister_netdev(dev);
- if (idev)
- pnp_device_detach(idev);
- /* Careful ne_drv_remove can be called twice, once from
- * the platform_driver.remove and again when the
- * platform_device is being removed.
- */
- ei_status.priv = 0;
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
- free_netdev(dev);
- }
-}
-
-/* Remove unused devices or all if true. */
-static void ne_loop_rm_unreg(int all)
-{
- int this_dev;
- struct platform_device *pdev;
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- pdev = pdev_ne[this_dev];
- /* No network device == unused */
- if (pdev && (!platform_get_drvdata(pdev) || all)) {
- ne_drv_remove(pdev);
- platform_device_unregister(pdev);
- pdev_ne[this_dev] = NULL;
- }
- }
-}
-
-#ifdef CONFIG_PM
-static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
-
- if (netif_running(dev)) {
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- netif_device_detach(dev);
- if (idev)
- pnp_stop_dev(idev);
- }
- return 0;
-}
-
-static int ne_drv_resume(struct platform_device *pdev)
-{
- struct net_device *dev = platform_get_drvdata(pdev);
-
- if (netif_running(dev)) {
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- if (idev)
- pnp_start_dev(idev);
- ne_reset_8390(dev);
- NS8390p_init(dev, 1);
- netif_device_attach(dev);
- }
- return 0;
-}
-#else
-#define ne_drv_suspend NULL
-#define ne_drv_resume NULL
-#endif
-
-static struct platform_driver ne_driver = {
- .remove = ne_drv_remove,
- .suspend = ne_drv_suspend,
- .resume = ne_drv_resume,
- .driver = {
- .name = DRV_NAME,
- },
-};
-
-static void __init ne_add_devices(void)
-{
- int this_dev;
- struct platform_device *pdev;
-
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- if (pdev_ne[this_dev])
- continue;
- pdev = platform_device_register_simple(
- DRV_NAME, this_dev, NULL, 0);
- if (IS_ERR(pdev))
- continue;
- pdev_ne[this_dev] = pdev;
- }
-}
-
-static int __init ne_init(void)
-{
- int retval;
-
- if (IS_MODULE(CONFIG_NE2000))
- ne_add_devices();
-
- retval = platform_driver_probe(&ne_driver, ne_drv_probe);
-
- if (IS_MODULE(CONFIG_NE2000) && retval) {
- if (io[0] == 0)
- pr_notice("ne.c: You must supply \"io=0xNNN\""
- " value(s) for ISA cards.\n");
- ne_loop_rm_unreg(1);
- return retval;
- }
-
- /* Unregister unused platform_devices. */
- ne_loop_rm_unreg(0);
- return retval;
-}
-module_init(ne_init);
-
-#if !defined(MODULE) && defined(CONFIG_NETDEV_LEGACY_INIT)
-struct net_device * __init ne_probe(int unit)
-{
- int this_dev;
- struct net_device *dev;
-
- /* Find an empty slot, that is no net_device and zero io port. */
- this_dev = 0;
- while ((pdev_ne[this_dev] && platform_get_drvdata(pdev_ne[this_dev])) ||
- io[this_dev]) {
- if (++this_dev == MAX_NE_CARDS)
- return ERR_PTR(-ENOMEM);
- }
-
- /* Get irq, io from kernel command line */
- dev = alloc_eip_netdev();
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
-
- io[this_dev] = dev->base_addr;
- irq[this_dev] = dev->irq;
- bad[this_dev] = dev->mem_end;
-
- free_netdev(dev);
-
- ne_add_devices();
-
- /* return the first device found */
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- if (pdev_ne[this_dev]) {
- dev = platform_get_drvdata(pdev_ne[this_dev]);
- if (dev)
- return dev;
- }
- }
-
- return ERR_PTR(-ENODEV);
-}
-#endif
-
-static void __exit ne_exit(void)
-{
- platform_driver_unregister(&ne_driver);
- ne_loop_rm_unreg(1);
-}
-module_exit(ne_exit);
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
deleted file mode 100644
index 19f9c5db3..000000000
--- a/drivers/net/ethernet/8390/pcnet_cs.c
+++ /dev/null
@@ -1,1717 +0,0 @@
-// SPDX-License-Identifier: GPL-1.0+
-/*======================================================================
-
- A PCMCIA ethernet driver for NS8390-based cards
-
- This driver supports the D-Link DE-650 and Linksys EthernetCard
- cards, the newer D-Link and Linksys combo cards, Accton EN2212
- cards, the RPTI EP400, and the PreMax PE-200 in non-shared-memory
- mode, and the IBM Credit Card Adapter, the NE4100, the Thomas
- Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
- mode. It will also handle the Socket EA card in either mode.
-
- Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
-
- pcnet_cs.c 1.153 2003/11/09 18:53:09
-
- The network driver code is based on Donald Becker's NE2000 code:
-
- Written 1992,1993 by Donald Becker.
- Copyright 1993 United States Government as represented by the
- Director, National Security Agency.
- Donald Becker may be reached at becker@scyld.com
-
- Based also on Keith Moore's changes to Don Becker's code, for IBM
- CCAE support. Drivers merged back together, and shared-memory
- Socket EA support added, by Ken Raeburn, September 1995.
-
-======================================================================*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/log2.h>
-#include <linux/etherdevice.h>
-#include <linux/mii.h>
-#include "8390.h"
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <linux/uaccess.h>
-
-#define PCNET_CMD 0x00
-#define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
-#define PCNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
-#define PCNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */
-
-#define PCNET_START_PG 0x40 /* First page of TX buffer */
-#define PCNET_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-/* Socket EA cards have a larger packet buffer */
-#define SOCKET_START_PG 0x01
-#define SOCKET_STOP_PG 0xff
-
-#define PCNET_RDC_TIMEOUT (2*HZ/100) /* Max wait in jiffies for Tx RDC */
-
-static const char *if_names[] = { "auto", "10baseT", "10base2"};
-
-/*====================================================================*/
-
-/* Module parameters */
-
-MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
-MODULE_DESCRIPTION("NE2000 compatible PCMCIA ethernet driver");
-MODULE_LICENSE("GPL");
-
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
-
-INT_MODULE_PARM(if_port, 1); /* Transceiver type */
-INT_MODULE_PARM(use_big_buf, 1); /* use 64K packet buffer? */
-INT_MODULE_PARM(mem_speed, 0); /* shared mem speed, in ns */
-INT_MODULE_PARM(delay_output, 0); /* pause after xmit? */
-INT_MODULE_PARM(delay_time, 4); /* in usec */
-INT_MODULE_PARM(use_shmem, -1); /* use shared memory? */
-INT_MODULE_PARM(full_duplex, 0); /* full duplex? */
-
-/* Ugh! Let the user hardwire the hardware address for queer cards */
-static int hw_addr[6] = { 0, /* ... */ };
-module_param_array(hw_addr, int, NULL, 0);
-
-/*====================================================================*/
-
-static void mii_phy_probe(struct net_device *dev);
-static int pcnet_config(struct pcmcia_device *link);
-static void pcnet_release(struct pcmcia_device *link);
-static int pcnet_open(struct net_device *dev);
-static int pcnet_close(struct net_device *dev);
-static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
-static void ei_watchdog(struct timer_list *t);
-static void pcnet_reset_8390(struct net_device *dev);
-static int set_config(struct net_device *dev, struct ifmap *map);
-static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
- int stop_pg, int cm_offset);
-static int setup_dma_config(struct pcmcia_device *link, int start_pg,
- int stop_pg);
-
-static void pcnet_detach(struct pcmcia_device *p_dev);
-
-/*====================================================================*/
-
-struct hw_info {
- u_int offset;
- u_char a0, a1, a2;
- u_int flags;
-};
-
-#define DELAY_OUTPUT 0x01
-#define HAS_MISC_REG 0x02
-#define USE_BIG_BUF 0x04
-#define HAS_IBM_MISC 0x08
-#define IS_DL10019 0x10
-#define IS_DL10022 0x20
-#define HAS_MII 0x40
-#define USE_SHMEM 0x80 /* autodetected */
-
-#define AM79C9XX_HOME_PHY 0x00006B90 /* HomePNA PHY */
-#define AM79C9XX_ETH_PHY 0x00006B70 /* 10baseT PHY */
-#define MII_PHYID_REV_MASK 0xfffffff0
-#define MII_PHYID_REG1 0x02
-#define MII_PHYID_REG2 0x03
-
-static struct hw_info hw_info[] = {
- { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
- { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
- { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
- { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94,
- DELAY_OUTPUT | HAS_IBM_MISC },
- { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 },
- { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 },
- { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 },
- { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 },
- { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 },
- { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 },
- { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 },
- { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 },
- { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 },
- { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 },
- { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 },
- { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 },
- { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 },
- { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
- { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45,
- HAS_MISC_REG | HAS_IBM_MISC },
- { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 },
- { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 },
- { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 },
- { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b,
- DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF },
- { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 },
- { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
- { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
- { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
- { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }
-};
-
-#define NR_INFO ARRAY_SIZE(hw_info)
-
-static struct hw_info default_info = { 0, 0, 0, 0, 0 };
-static struct hw_info dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
-static struct hw_info dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
-
-struct pcnet_dev {
- struct pcmcia_device *p_dev;
- u_int flags;
- void __iomem *base;
- struct timer_list watchdog;
- int stale, fast_poll;
- u_char phy_id;
- u_char eth_phy, pna_phy;
- u_short link_status;
- u_long mii_reset;
-};
-
-static inline struct pcnet_dev *PRIV(struct net_device *dev)
-{
- char *p = netdev_priv(dev);
- return (struct pcnet_dev *)(p + sizeof(struct ei_device));
-}
-
-static const struct net_device_ops pcnet_netdev_ops = {
- .ndo_open = pcnet_open,
- .ndo_stop = pcnet_close,
- .ndo_set_config = set_config,
- .ndo_start_xmit = ei_start_xmit,
- .ndo_get_stats = ei_get_stats,
- .ndo_eth_ioctl = ei_ioctl,
- .ndo_set_rx_mode = ei_set_multicast_list,
- .ndo_tx_timeout = ei_tx_timeout,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ei_poll,
-#endif
-};
-
-static int pcnet_probe(struct pcmcia_device *link)
-{
- struct pcnet_dev *info;
- struct net_device *dev;
-
- dev_dbg(&link->dev, "pcnet_attach()\n");
-
- /* Create new ethernet device */
- dev = __alloc_ei_netdev(sizeof(struct pcnet_dev));
- if (!dev) return -ENOMEM;
- info = PRIV(dev);
- info->p_dev = link;
- link->priv = dev;
-
- link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
- dev->netdev_ops = &pcnet_netdev_ops;
-
- return pcnet_config(link);
-} /* pcnet_attach */
-
-static void pcnet_detach(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
-
- dev_dbg(&link->dev, "pcnet_detach\n");
-
- unregister_netdev(dev);
-
- pcnet_release(link);
-
- free_netdev(dev);
-} /* pcnet_detach */
-
-/*======================================================================
-
- This probes for a card's hardware address, for card types that
- encode this information in their CIS.
-
-======================================================================*/
-
-static struct hw_info *get_hwinfo(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
- u_char __iomem *base, *virt;
- u8 addr[ETH_ALEN];
- int i, j;
-
- /* Allocate a small memory window */
- link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- link->resource[2]->start = 0; link->resource[2]->end = 0;
- i = pcmcia_request_window(link, link->resource[2], 0);
- if (i != 0)
- return NULL;
-
- virt = ioremap(link->resource[2]->start,
- resource_size(link->resource[2]));
- if (unlikely(!virt)) {
- pcmcia_release_window(link, link->resource[2]);
- return NULL;
- }
-
- for (i = 0; i < NR_INFO; i++) {
- pcmcia_map_mem_page(link, link->resource[2],
- hw_info[i].offset & ~(resource_size(link->resource[2])-1));
- base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)];
- if ((readb(base+0) == hw_info[i].a0) &&
- (readb(base+2) == hw_info[i].a1) &&
- (readb(base+4) == hw_info[i].a2)) {
- for (j = 0; j < 6; j++)
- addr[j] = readb(base + (j<<1));
- eth_hw_addr_set(dev, addr);
- break;
- }
- }
-
- iounmap(virt);
- j = pcmcia_release_window(link, link->resource[2]);
- return (i < NR_INFO) ? hw_info+i : NULL;
-} /* get_hwinfo */
-
-/*======================================================================
-
- This probes for a card's hardware address by reading the PROM.
- It checks the address against a list of known types, then falls
- back to a simple NE2000 clone signature check.
-
-======================================================================*/
-
-static struct hw_info *get_prom(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
- unsigned int ioaddr = dev->base_addr;
- u8 addr[ETH_ALEN];
- u_char prom[32];
- int i, j;
-
- /* This is lifted straight from drivers/net/ethernet/8390/ne.c */
- struct {
- u_char value, offset;
- } program_seq[] = {
- {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
- {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
- {0x00, EN0_RCNTLO}, /* Clear the count regs. */
- {0x00, EN0_RCNTHI},
- {0x00, EN0_IMR}, /* Mask completion irq. */
- {0xFF, EN0_ISR},
- {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
- {32, EN0_RCNTLO},
- {0x00, EN0_RCNTHI},
- {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
- {0x00, EN0_RSARHI},
- {E8390_RREAD+E8390_START, E8390_CMD},
- };
-
- pcnet_reset_8390(dev);
- mdelay(10);
-
- for (i = 0; i < ARRAY_SIZE(program_seq); i++)
- outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
- for (i = 0; i < 32; i++)
- prom[i] = inb(ioaddr + PCNET_DATAPORT);
- for (i = 0; i < NR_INFO; i++) {
- if ((prom[0] == hw_info[i].a0) &&
- (prom[2] == hw_info[i].a1) &&
- (prom[4] == hw_info[i].a2))
- break;
- }
- if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
- for (j = 0; j < 6; j++)
- addr[j] = prom[j<<1];
- eth_hw_addr_set(dev, addr);
- return (i < NR_INFO) ? hw_info+i : &default_info;
- }
- return NULL;
-} /* get_prom */
-
-/*======================================================================
-
- For DL10019 based cards, like the Linksys EtherFast
-
-======================================================================*/
-
-static struct hw_info *get_dl10019(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
- u8 addr[ETH_ALEN];
- int i;
- u_char sum;
-
- for (sum = 0, i = 0x14; i < 0x1c; i++)
- sum += inb_p(dev->base_addr + i);
- if (sum != 0xff)
- return NULL;
- for (i = 0; i < 6; i++)
- addr[i] = inb_p(dev->base_addr + 0x14 + i);
- eth_hw_addr_set(dev, addr);
- i = inb(dev->base_addr + 0x1f);
- return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info;
-}
-
-/*======================================================================
-
- For Asix AX88190 based cards
-
-======================================================================*/
-
-static struct hw_info *get_ax88190(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
- unsigned int ioaddr = dev->base_addr;
- u8 addr[ETH_ALEN];
- int i, j;
-
- /* Not much of a test, but the alternatives are messy */
- if (link->config_base != 0x03c0)
- return NULL;
-
- outb_p(0x01, ioaddr + EN0_DCFG); /* Set word-wide access. */
- outb_p(0x00, ioaddr + EN0_RSARLO); /* DMA starting at 0x0400. */
- outb_p(0x04, ioaddr + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, ioaddr + E8390_CMD);
-
- for (i = 0; i < 6; i += 2) {
- j = inw(ioaddr + PCNET_DATAPORT);
- addr[i] = j & 0xff;
- addr[i+1] = j >> 8;
- }
- eth_hw_addr_set(dev, addr);
- return NULL;
-}
-
-/*======================================================================
-
- This should be totally unnecessary... but when we can't figure
- out the hardware address any other way, we'll let the user hard
- wire it when the module is initialized.
-
-======================================================================*/
-
-static struct hw_info *get_hwired(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
- u8 addr[ETH_ALEN];
- int i;
-
- for (i = 0; i < 6; i++)
- if (hw_addr[i] != 0) break;
- if (i == 6)
- return NULL;
-
- for (i = 0; i < 6; i++)
- addr[i] = hw_addr[i];
- eth_hw_addr_set(dev, addr);
-
- return &default_info;
-} /* get_hwired */
-
-static int try_io_port(struct pcmcia_device *link)
-{
- int j, ret;
- link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
- link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
- if (link->resource[0]->end == 32) {
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- if (link->resource[1]->end > 0) {
- /* for master/slave multifunction cards */
- link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
- }
- } else {
- /* This should be two 16-port windows */
- link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
- link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
- }
- if (link->resource[0]->start == 0) {
- for (j = 0; j < 0x400; j += 0x20) {
- link->resource[0]->start = j ^ 0x300;
- link->resource[1]->start = (j ^ 0x300) + 0x10;
- link->io_lines = 16;
- ret = pcmcia_request_io(link);
- if (ret == 0)
- return ret;
- }
- return ret;
- } else {
- return pcmcia_request_io(link);
- }
-}
-
-static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
-{
- int *priv = priv_data;
- int try = (*priv & 0x1);
-
- *priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
-
- if (p_dev->config_index == 0)
- return -EINVAL;
-
- if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
- return -EINVAL;
-
- if (try)
- p_dev->io_lines = 16;
- return try_io_port(p_dev);
-}
-
-static struct hw_info *pcnet_try_config(struct pcmcia_device *link,
- int *has_shmem, int try)
-{
- struct net_device *dev = link->priv;
- struct hw_info *local_hw_info;
- struct pcnet_dev *info = PRIV(dev);
- int priv = try;
- int ret;
-
- ret = pcmcia_loop_config(link, pcnet_confcheck, &priv);
- if (ret) {
- dev_warn(&link->dev, "no useable port range found\n");
- return NULL;
- }
- *has_shmem = (priv & 0x10);
-
- if (!link->irq)
- return NULL;
-
- if (resource_size(link->resource[1]) == 8)
- link->config_flags |= CONF_ENABLE_SPKR;
-
- if ((link->manf_id == MANFID_IBM) &&
- (link->card_id == PRODID_IBM_HOME_AND_AWAY))
- link->config_index |= 0x10;
-
- ret = pcmcia_enable_device(link);
- if (ret)
- return NULL;
-
- dev->irq = link->irq;
- dev->base_addr = link->resource[0]->start;
-
- if (info->flags & HAS_MISC_REG) {
- if ((if_port == 1) || (if_port == 2))
- dev->if_port = if_port;
- else
- dev_notice(&link->dev, "invalid if_port requested\n");
- } else
- dev->if_port = 0;
-
- if ((link->config_base == 0x03c0) &&
- (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
- dev_info(&link->dev,
- "this is an AX88190 card - use axnet_cs instead.\n");
- return NULL;
- }
-
- local_hw_info = get_hwinfo(link);
- if (!local_hw_info)
- local_hw_info = get_prom(link);
- if (!local_hw_info)
- local_hw_info = get_dl10019(link);
- if (!local_hw_info)
- local_hw_info = get_ax88190(link);
- if (!local_hw_info)
- local_hw_info = get_hwired(link);
-
- return local_hw_info;
-}
-
-static int pcnet_config(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
- struct pcnet_dev *info = PRIV(dev);
- int start_pg, stop_pg, cm_offset;
- int has_shmem = 0;
- struct hw_info *local_hw_info;
-
- dev_dbg(&link->dev, "pcnet_config\n");
-
- local_hw_info = pcnet_try_config(link, &has_shmem, 0);
- if (!local_hw_info) {
- /* check whether forcing io_lines to 16 helps... */
- pcmcia_disable_device(link);
- local_hw_info = pcnet_try_config(link, &has_shmem, 1);
- if (local_hw_info == NULL) {
- dev_notice(&link->dev, "unable to read hardware net"
- " address for io base %#3lx\n", dev->base_addr);
- goto failed;
- }
- }
-
- info->flags = local_hw_info->flags;
- /* Check for user overrides */
- info->flags |= (delay_output) ? DELAY_OUTPUT : 0;
- if ((link->manf_id == MANFID_SOCKET) &&
- ((link->card_id == PRODID_SOCKET_LPE) ||
- (link->card_id == PRODID_SOCKET_LPE_CF) ||
- (link->card_id == PRODID_SOCKET_EIO)))
- info->flags &= ~USE_BIG_BUF;
- if (!use_big_buf)
- info->flags &= ~USE_BIG_BUF;
-
- if (info->flags & USE_BIG_BUF) {
- start_pg = SOCKET_START_PG;
- stop_pg = SOCKET_STOP_PG;
- cm_offset = 0x10000;
- } else {
- start_pg = PCNET_START_PG;
- stop_pg = PCNET_STOP_PG;
- cm_offset = 0;
- }
-
- /* has_shmem is ignored if use_shmem != -1 */
- if ((use_shmem == 0) || (!has_shmem && (use_shmem == -1)) ||
- (setup_shmem_window(link, start_pg, stop_pg, cm_offset) != 0))
- setup_dma_config(link, start_pg, stop_pg);
-
- ei_status.name = "NE2000";
- ei_status.word16 = 1;
- ei_status.reset_8390 = pcnet_reset_8390;
-
- if (info->flags & (IS_DL10019|IS_DL10022))
- mii_phy_probe(dev);
-
- SET_NETDEV_DEV(dev, &link->dev);
-
- if (register_netdev(dev) != 0) {
- pr_notice("register_netdev() failed\n");
- goto failed;
- }
-
- if (info->flags & (IS_DL10019|IS_DL10022)) {
- u_char id = inb(dev->base_addr + 0x1a);
- netdev_info(dev, "NE2000 (DL100%d rev %02x): ",
- (info->flags & IS_DL10022) ? 22 : 19, id);
- if (info->pna_phy)
- pr_cont("PNA, ");
- } else {
- netdev_info(dev, "NE2000 Compatible: ");
- }
- pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq);
- if (info->flags & USE_SHMEM)
- pr_cont(" mem %#5lx,", dev->mem_start);
- if (info->flags & HAS_MISC_REG)
- pr_cont(" %s xcvr,", if_names[dev->if_port]);
- pr_cont(" hw_addr %pM\n", dev->dev_addr);
- return 0;
-
-failed:
- pcnet_release(link);
- return -ENODEV;
-} /* pcnet_config */
-
-static void pcnet_release(struct pcmcia_device *link)
-{
- struct pcnet_dev *info = PRIV(link->priv);
-
- dev_dbg(&link->dev, "pcnet_release\n");
-
- if (info->flags & USE_SHMEM)
- iounmap(info->base);
-
- pcmcia_disable_device(link);
-}
-
-static int pcnet_suspend(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
-
- if (link->open)
- netif_device_detach(dev);
-
- return 0;
-}
-
-static int pcnet_resume(struct pcmcia_device *link)
-{
- struct net_device *dev = link->priv;
-
- if (link->open) {
- pcnet_reset_8390(dev);
- NS8390_init(dev, 1);
- netif_device_attach(dev);
- }
-
- return 0;
-}
-
-
-/*======================================================================
-
- MII interface support for DL10019 and DL10022 based cards
-
- On the DL10019, the MII IO direction bit is 0x10; on the DL10022
- it is 0x20. Setting both bits seems to work on both card types.
-
-======================================================================*/
-
-#define DLINK_GPIO 0x1c
-#define DLINK_DIAG 0x1d
-#define DLINK_EEPROM 0x1e
-
-#define MDIO_SHIFT_CLK 0x80
-#define MDIO_DATA_OUT 0x40
-#define MDIO_DIR_WRITE 0x30
-#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE)
-#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
-#define MDIO_DATA_READ 0x10
-#define MDIO_MASK 0x0f
-
-static void mdio_sync(unsigned int addr)
-{
- int bits, mask = inb(addr) & MDIO_MASK;
- for (bits = 0; bits < 32; bits++) {
- outb(mask | MDIO_DATA_WRITE1, addr);
- outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
- }
-}
-
-static int mdio_read(unsigned int addr, int phy_id, int loc)
-{
- u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
- int i, retval = 0, mask = inb(addr) & MDIO_MASK;
-
- mdio_sync(addr);
- for (i = 13; i >= 0; i--) {
- int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
- outb(mask | dat, addr);
- outb(mask | dat | MDIO_SHIFT_CLK, addr);
- }
- for (i = 19; i > 0; i--) {
- outb(mask, addr);
- retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
- outb(mask | MDIO_SHIFT_CLK, addr);
- }
- return (retval>>1) & 0xffff;
-}
-
-static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
-{
- u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
- int i, mask = inb(addr) & MDIO_MASK;
-
- mdio_sync(addr);
- for (i = 31; i >= 0; i--) {
- int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
- outb(mask | dat, addr);
- outb(mask | dat | MDIO_SHIFT_CLK, addr);
- }
- for (i = 1; i >= 0; i--) {
- outb(mask, addr);
- outb(mask | MDIO_SHIFT_CLK, addr);
- }
-}
-
-/*======================================================================
-
- EEPROM access routines for DL10019 and DL10022 based cards
-
-======================================================================*/
-
-#define EE_EEP 0x40
-#define EE_ASIC 0x10
-#define EE_CS 0x08
-#define EE_CK 0x04
-#define EE_DO 0x02
-#define EE_DI 0x01
-#define EE_ADOT 0x01 /* DataOut for ASIC */
-#define EE_READ_CMD 0x06
-
-#define DL19FDUPLX 0x0400 /* DL10019 Full duplex mode */
-
-static int read_eeprom(unsigned int ioaddr, int location)
-{
- int i, retval = 0;
- unsigned int ee_addr = ioaddr + DLINK_EEPROM;
- int read_cmd = location | (EE_READ_CMD << 8);
-
- outb(0, ee_addr);
- outb(EE_EEP|EE_CS, ee_addr);
-
- /* Shift the read command bits out. */
- for (i = 10; i >= 0; i--) {
- short dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
- outb_p(EE_EEP|EE_CS|dataval, ee_addr);
- outb_p(EE_EEP|EE_CS|dataval|EE_CK, ee_addr);
- }
- outb(EE_EEP|EE_CS, ee_addr);
-
- for (i = 16; i > 0; i--) {
- outb_p(EE_EEP|EE_CS | EE_CK, ee_addr);
- retval = (retval << 1) | ((inb(ee_addr) & EE_DI) ? 1 : 0);
- outb_p(EE_EEP|EE_CS, ee_addr);
- }
-
- /* Terminate the EEPROM access. */
- outb(0, ee_addr);
- return retval;
-}
-
-/*
- The internal ASIC registers can be changed by EEPROM READ access
- with EE_ASIC bit set.
- In ASIC mode, EE_ADOT is used to output the data to the ASIC.
-*/
-
-static void write_asic(unsigned int ioaddr, int location, short asic_data)
-{
- int i;
- unsigned int ee_addr = ioaddr + DLINK_EEPROM;
- short dataval;
- int read_cmd = location | (EE_READ_CMD << 8);
-
- asic_data |= read_eeprom(ioaddr, location);
-
- outb(0, ee_addr);
- outb(EE_ASIC|EE_CS|EE_DI, ee_addr);
-
- read_cmd = read_cmd >> 1;
-
- /* Shift the read command bits out. */
- for (i = 9; i >= 0; i--) {
- dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
- outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
- outb_p(EE_ASIC|EE_CS|EE_DI|dataval|EE_CK, ee_addr);
- outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
- }
- // sync
- outb(EE_ASIC|EE_CS, ee_addr);
- outb(EE_ASIC|EE_CS|EE_CK, ee_addr);
- outb(EE_ASIC|EE_CS, ee_addr);
-
- for (i = 15; i >= 0; i--) {
- dataval = (asic_data & (1 << i)) ? EE_ADOT : 0;
- outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
- outb_p(EE_ASIC|EE_CS|dataval|EE_CK, ee_addr);
- outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
- }
-
- /* Terminate the ASIC access. */
- outb(EE_ASIC|EE_DI, ee_addr);
- outb(EE_ASIC|EE_DI| EE_CK, ee_addr);
- outb(EE_ASIC|EE_DI, ee_addr);
-
- outb(0, ee_addr);
-}
-
-/*====================================================================*/
-
-static void set_misc_reg(struct net_device *dev)
-{
- unsigned int nic_base = dev->base_addr;
- struct pcnet_dev *info = PRIV(dev);
- u_char tmp;
-
- if (info->flags & HAS_MISC_REG) {
- tmp = inb_p(nic_base + PCNET_MISC) & ~3;
- if (dev->if_port == 2)
- tmp |= 1;
- if (info->flags & USE_BIG_BUF)
- tmp |= 2;
- if (info->flags & HAS_IBM_MISC)
- tmp |= 8;
- outb_p(tmp, nic_base + PCNET_MISC);
- }
- if (info->flags & IS_DL10022) {
- if (info->flags & HAS_MII) {
- /* Advertise 100F, 100H, 10F, 10H */
- mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
- /* Restart MII autonegotiation */
- mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
- mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
- info->mii_reset = jiffies;
- } else {
- outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG);
- }
- } else if (info->flags & IS_DL10019) {
- /* Advertise 100F, 100H, 10F, 10H */
- mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
- /* Restart MII autonegotiation */
- mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
- mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
- }
-}
-
-/*====================================================================*/
-
-static void mii_phy_probe(struct net_device *dev)
-{
- struct pcnet_dev *info = PRIV(dev);
- unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
- int i;
- u_int tmp, phyid;
-
- for (i = 31; i >= 0; i--) {
- tmp = mdio_read(mii_addr, i, 1);
- if ((tmp == 0) || (tmp == 0xffff))
- continue;
- tmp = mdio_read(mii_addr, i, MII_PHYID_REG1);
- phyid = tmp << 16;
- phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);
- phyid &= MII_PHYID_REV_MASK;
- netdev_dbg(dev, "MII at %d is 0x%08x\n", i, phyid);
- if (phyid == AM79C9XX_HOME_PHY) {
- info->pna_phy = i;
- } else if (phyid != AM79C9XX_ETH_PHY) {
- info->eth_phy = i;
- }
- }
-}
-
-static int pcnet_open(struct net_device *dev)
-{
- int ret;
- struct pcnet_dev *info = PRIV(dev);
- struct pcmcia_device *link = info->p_dev;
- unsigned int nic_base = dev->base_addr;
-
- dev_dbg(&link->dev, "pcnet_open('%s')\n", dev->name);
-
- if (!pcmcia_dev_present(link))
- return -ENODEV;
-
- set_misc_reg(dev);
-
- outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
- ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev->name, dev);
- if (ret)
- return ret;
-
- link->open++;
-
- info->phy_id = info->eth_phy;
- info->link_status = 0x00;
- timer_setup(&info->watchdog, ei_watchdog, 0);
- mod_timer(&info->watchdog, jiffies + HZ);
-
- return ei_open(dev);
-} /* pcnet_open */
-
-/*====================================================================*/
-
-static int pcnet_close(struct net_device *dev)
-{
- struct pcnet_dev *info = PRIV(dev);
- struct pcmcia_device *link = info->p_dev;
-
- dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);
-
- ei_close(dev);
- free_irq(dev->irq, dev);
-
- link->open--;
- netif_stop_queue(dev);
- timer_delete_sync(&info->watchdog);
-
- return 0;
-} /* pcnet_close */
-
-/*======================================================================
-
- Hard reset the card. This used to pause for the same period that
- a 8390 reset command required, but that shouldn't be necessary.
-
-======================================================================*/
-
-static void pcnet_reset_8390(struct net_device *dev)
-{
- unsigned int nic_base = dev->base_addr;
- int i;
-
- ei_status.txing = ei_status.dmaing = 0;
-
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
-
- outb(inb(nic_base + PCNET_RESET), nic_base + PCNET_RESET);
-
- for (i = 0; i < 100; i++) {
- if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
- break;
- udelay(100);
- }
- outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
-
- if (i == 100)
- netdev_err(dev, "pcnet_reset_8390() did not complete.\n");
-
- set_misc_reg(dev);
-
-} /* pcnet_reset_8390 */
-
-/*====================================================================*/
-
-static int set_config(struct net_device *dev, struct ifmap *map)
-{
- struct pcnet_dev *info = PRIV(dev);
- if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
- if (!(info->flags & HAS_MISC_REG))
- return -EOPNOTSUPP;
- else if ((map->port < 1) || (map->port > 2))
- return -EINVAL;
- WRITE_ONCE(dev->if_port, map->port);
- netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
- NS8390_init(dev, 1);
- }
- return 0;
-}
-
-/*====================================================================*/
-
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct pcnet_dev *info;
- irqreturn_t ret = ei_interrupt(irq, dev_id);
-
- if (ret == IRQ_HANDLED) {
- info = PRIV(dev);
- info->stale = 0;
- }
- return ret;
-}
-
-static void ei_watchdog(struct timer_list *t)
-{
- struct pcnet_dev *info = timer_container_of(info, t, watchdog);
- struct net_device *dev = info->p_dev->priv;
- unsigned int nic_base = dev->base_addr;
- unsigned int mii_addr = nic_base + DLINK_GPIO;
- u_short link;
-
- if (!netif_device_present(dev)) goto reschedule;
-
- /* Check for pending interrupt with expired latency timer: with
- this, we can limp along even if the interrupt is blocked */
- if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
- if (!info->fast_poll)
- netdev_info(dev, "interrupt(s) dropped!\n");
- ei_irq_wrapper(dev->irq, dev);
- info->fast_poll = HZ;
- }
- if (info->fast_poll) {
- info->fast_poll--;
- info->watchdog.expires = jiffies + 1;
- add_timer(&info->watchdog);
- return;
- }
-
- if (!(info->flags & HAS_MII))
- goto reschedule;
-
- mdio_read(mii_addr, info->phy_id, 1);
- link = mdio_read(mii_addr, info->phy_id, 1);
- if (!link || (link == 0xffff)) {
- if (info->eth_phy) {
- info->phy_id = info->eth_phy = 0;
- } else {
- netdev_info(dev, "MII is missing!\n");
- info->flags &= ~HAS_MII;
- }
- goto reschedule;
- }
-
- link &= 0x0004;
- if (link != info->link_status) {
- u_short p = mdio_read(mii_addr, info->phy_id, 5);
- netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
- if (link && (info->flags & IS_DL10022)) {
- /* Disable collision detection on full duplex links */
- outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
- } else if (link && (info->flags & IS_DL10019)) {
- /* Disable collision detection on full duplex links */
- write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0);
- }
- if (link) {
- if (info->phy_id == info->eth_phy) {
- if (p)
- netdev_info(dev, "autonegotiation complete: "
- "%sbaseT-%cD selected\n",
- ((p & 0x0180) ? "100" : "10"),
- ((p & 0x0140) ? 'F' : 'H'));
- else
- netdev_info(dev, "link partner did not autonegotiate\n");
- }
- NS8390_init(dev, 1);
- }
- info->link_status = link;
- }
- if (info->pna_phy && time_after(jiffies, info->mii_reset + 6*HZ)) {
- link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004;
- if (((info->phy_id == info->pna_phy) && link) ||
- ((info->phy_id != info->pna_phy) && !link)) {
- /* isolate this MII and try flipping to the other one */
- mdio_write(mii_addr, info->phy_id, 0, 0x0400);
- info->phy_id ^= info->pna_phy ^ info->eth_phy;
- netdev_info(dev, "switched to %s transceiver\n",
- (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
- mdio_write(mii_addr, info->phy_id, 0,
- (info->phy_id == info->eth_phy) ? 0x1000 : 0);
- info->link_status = 0;
- info->mii_reset = jiffies;
- }
- }
-
-reschedule:
- info->watchdog.expires = jiffies + HZ;
- add_timer(&info->watchdog);
-}
-
-/*====================================================================*/
-
-
-static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct pcnet_dev *info = PRIV(dev);
- struct mii_ioctl_data *data = if_mii(rq);
- unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
-
- if (!(info->flags & (IS_DL10019|IS_DL10022)))
- return -EINVAL;
-
- switch (cmd) {
- case SIOCGMIIPHY:
- data->phy_id = info->phy_id;
- fallthrough;
- case SIOCGMIIREG: /* Read MII PHY register. */
- data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
- return 0;
- case SIOCSMIIREG: /* Write MII PHY register. */
- mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
- return 0;
- }
- return -EOPNOTSUPP;
-}
-
-/*====================================================================*/
-
-static void dma_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr,
- int ring_page)
-{
- unsigned int nic_base = dev->base_addr;
-
- if (ei_status.dmaing) {
- netdev_err(dev, "DMAing conflict in dma_block_input."
- "[DMAstat:%1x][irqlock:%1x]\n",
- ei_status.dmaing, ei_status.irqlock);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
- outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
- outb_p(0, nic_base + EN0_RCNTHI);
- outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
- outb_p(ring_page, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
-
- insw(nic_base + PCNET_DATAPORT, hdr,
- sizeof(struct e8390_pkt_hdr)>>1);
- /* Fix for big endian systems */
- hdr->count = le16_to_cpu(hdr->count);
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-/*====================================================================*/
-
-static void dma_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- unsigned int nic_base = dev->base_addr;
- int xfer_count = count;
- char *buf = skb->data;
- struct ei_device *ei_local = netdev_priv(dev);
-
- if ((netif_msg_rx_status(ei_local)) && (count != 4))
- netdev_dbg(dev, "[bi=%d]\n", count+4);
- if (ei_status.dmaing) {
- netdev_err(dev, "DMAing conflict in dma_block_input."
- "[DMAstat:%1x][irqlock:%1x]\n",
- ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
- outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
-
- insw(nic_base + PCNET_DATAPORT,buf,count>>1);
- if (count & 0x01) {
- buf[count-1] = inb(nic_base + PCNET_DATAPORT);
- xfer_count++;
- }
-
- /* This was for the ALPHA version only, but enough people have been
- encountering problems that it is still here. */
-#ifdef PCMCIA_DEBUG
- /* DMA termination address check... */
- if (netif_msg_rx_status(ei_local)) {
- int addr, tries = 20;
- do {
- /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
- -- it's broken for Rx on some cards! */
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if (((ring_offset + xfer_count) & 0xff) == (addr & 0xff))
- break;
- } while (--tries > 0);
- if (tries <= 0)
- netdev_notice(dev, "RX transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- ring_offset + xfer_count, addr);
- }
-#endif
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-} /* dma_block_input */
-
-/*====================================================================*/
-
-static void dma_block_output(struct net_device *dev, int count,
- const u_char *buf, const int start_page)
-{
- unsigned int nic_base = dev->base_addr;
- struct pcnet_dev *info = PRIV(dev);
-#ifdef PCMCIA_DEBUG
- int retries = 0;
- struct ei_device *ei_local = netdev_priv(dev);
-#endif
- u_long dma_start;
-
-#ifdef PCMCIA_DEBUG
- netif_dbg(ei_local, tx_queued, dev, "[bo=%d]\n", count);
-#endif
-
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
- if (count & 0x01)
- count++;
- if (ei_status.dmaing) {
- netdev_err(dev, "DMAing conflict in dma_block_output."
- "[DMAstat:%1x][irqlock:%1x]\n",
- ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base+PCNET_CMD);
-
-#ifdef PCMCIA_DEBUG
- retry:
-#endif
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR);
-
- /* Now the normal output. */
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(0x00, nic_base + EN0_RSARLO);
- outb_p(start_page, nic_base + EN0_RSARHI);
-
- outb_p(E8390_RWRITE+E8390_START, nic_base + PCNET_CMD);
- outsw(nic_base + PCNET_DATAPORT, buf, count>>1);
-
- dma_start = jiffies;
-
-#ifdef PCMCIA_DEBUG
- /* This was for the ALPHA version only, but enough people have been
- encountering problems that it is still here. */
- /* DMA termination address check... */
- if (netif_msg_tx_queued(ei_local)) {
- int addr, tries = 20;
- do {
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if ((start_page << 8) + count == addr)
- break;
- } while (--tries > 0);
- if (tries <= 0) {
- netdev_notice(dev, "Tx packet transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- (start_page << 8) + count, addr);
- if (retries++ == 0)
- goto retry;
- }
- }
-#endif
-
- while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) {
- netdev_warn(dev, "timeout waiting for Tx RDC.\n");
- pcnet_reset_8390(dev);
- NS8390_init(dev, 1);
- break;
- }
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- if (info->flags & DELAY_OUTPUT)
- udelay((long)delay_time);
- ei_status.dmaing &= ~0x01;
-}
-
-/*====================================================================*/
-
-static int setup_dma_config(struct pcmcia_device *link, int start_pg,
- int stop_pg)
-{
- struct net_device *dev = link->priv;
-
- ei_status.tx_start_page = start_pg;
- ei_status.rx_start_page = start_pg + TX_PAGES;
- ei_status.stop_page = stop_pg;
-
- /* set up block i/o functions */
- ei_status.get_8390_hdr = dma_get_8390_hdr;
- ei_status.block_input = dma_block_input;
- ei_status.block_output = dma_block_output;
-
- return 0;
-}
-
-/*====================================================================*/
-
-static void copyin(void *dest, void __iomem *src, int c)
-{
- u_short *d = dest;
- u_short __iomem *s = src;
- int odd;
-
- if (c <= 0)
- return;
- odd = (c & 1); c >>= 1;
-
- if (c) {
- do { *d++ = __raw_readw(s++); } while (--c);
- }
- /* get last byte by fetching a word and masking */
- if (odd)
- *((u_char *)d) = readw(s) & 0xff;
-}
-
-static void copyout(void __iomem *dest, const void *src, int c)
-{
- u_short __iomem *d = dest;
- const u_short *s = src;
- int odd;
-
- if (c <= 0)
- return;
- odd = (c & 1); c >>= 1;
-
- if (c) {
- do { __raw_writew(*s++, d++); } while (--c);
- }
- /* copy last byte doing a read-modify-write */
- if (odd)
- writew((readw(d) & 0xff00) | *(u_char *)s, d);
-}
-
-/*====================================================================*/
-
-static void shmem_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr,
- int ring_page)
-{
- void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
- + (ring_page << 8)
- - (ei_status.rx_start_page << 8);
-
- copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr));
- /* Fix for big endian systems */
- hdr->count = le16_to_cpu(hdr->count);
-}
-
-/*====================================================================*/
-
-static void shmem_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- void __iomem *base = ei_status.mem;
- unsigned long offset = (TX_PAGES<<8) + ring_offset
- - (ei_status.rx_start_page << 8);
- char *buf = skb->data;
-
- if (offset + count > ei_status.priv) {
- /* We must wrap the input move. */
- int semi_count = ei_status.priv - offset;
- copyin(buf, base + offset, semi_count);
- buf += semi_count;
- offset = TX_PAGES<<8;
- count -= semi_count;
- }
- copyin(buf, base + offset, count);
-}
-
-/*====================================================================*/
-
-static void shmem_block_output(struct net_device *dev, int count,
- const u_char *buf, const int start_page)
-{
- void __iomem *shmem = ei_status.mem + (start_page << 8);
- shmem -= ei_status.tx_start_page << 8;
- copyout(shmem, buf, count);
-}
-
-/*====================================================================*/
-
-static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
- int stop_pg, int cm_offset)
-{
- struct net_device *dev = link->priv;
- struct pcnet_dev *info = PRIV(dev);
- int i, window_size, offset, ret;
-
- window_size = (stop_pg - start_pg) << 8;
- if (window_size > 32 * 1024)
- window_size = 32 * 1024;
-
- /* Make sure it's a power of two. */
- window_size = roundup_pow_of_two(window_size);
-
- /* Allocate a memory window */
- link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
- link->resource[3]->flags |= WIN_USE_WAIT;
- link->resource[3]->start = 0; link->resource[3]->end = window_size;
- ret = pcmcia_request_window(link, link->resource[3], mem_speed);
- if (ret)
- goto failed;
-
- offset = (start_pg << 8) + cm_offset;
- offset -= offset % window_size;
- ret = pcmcia_map_mem_page(link, link->resource[3], offset);
- if (ret)
- goto failed;
-
- /* Try scribbling on the buffer */
- info->base = ioremap(link->resource[3]->start,
- resource_size(link->resource[3]));
- if (unlikely(!info->base)) {
- ret = -ENOMEM;
- goto failed;
- }
-
- for (i = 0; i < (TX_PAGES<<8); i += 2)
- __raw_writew((i>>1), info->base+offset+i);
- udelay(100);
- for (i = 0; i < (TX_PAGES<<8); i += 2)
- if (__raw_readw(info->base+offset+i) != (i>>1)) break;
- pcnet_reset_8390(dev);
- if (i != (TX_PAGES<<8)) {
- iounmap(info->base);
- pcmcia_release_window(link, link->resource[3]);
- info->base = NULL;
- goto failed;
- }
-
- ei_status.mem = info->base + offset;
- ei_status.priv = resource_size(link->resource[3]);
- dev->mem_start = (u_long)ei_status.mem;
- dev->mem_end = dev->mem_start + resource_size(link->resource[3]);
-
- ei_status.tx_start_page = start_pg;
- ei_status.rx_start_page = start_pg + TX_PAGES;
- ei_status.stop_page = start_pg + (
- (resource_size(link->resource[3]) - offset) >> 8);
-
- /* set up block i/o functions */
- ei_status.get_8390_hdr = shmem_get_8390_hdr;
- ei_status.block_input = shmem_block_input;
- ei_status.block_output = shmem_block_output;
-
- info->flags |= USE_SHMEM;
- return 0;
-
-failed:
- return 1;
-}
-
-/*====================================================================*/
-
-static const struct pcmcia_device_id pcnet_ids[] = {
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101),
- PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
- PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
- PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
- PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
- PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
- PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
- PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
- PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004),
- PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d),
- PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075),
- PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145),
- PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230),
- PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530),
- PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab),
- PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110),
- PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041),
- PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307),
- PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a),
- PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
- PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
- PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0009),
- PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
- PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
- PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0),
- PCMCIA_DEVICE_PROD_ID123("EFA ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0),
- PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82),
- PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8),
- PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab),
- PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11),
- PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8),
- PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247),
- PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96),
- PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1),
- PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd),
- PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190),
- PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504),
- PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a),
- PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79),
- PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7),
- PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a),
- PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9),
- PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
- PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
- PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether CF-TD LAN Card", 0x5261440f, 0x8797663b),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
- PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
- PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
- PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
- PCMCIA_DEVICE_PROD_ID12("corega K.K.", "(CG-LAPCCTXD)", 0x5261440f, 0x73ec0d88),
- PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04),
- PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d),
- PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814),
- PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0),
- PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf),
- PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995),
- PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233),
- PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e),
- PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398),
- PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b),
- PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660+", 0x1a424a1c, 0x50dcd0ec),
- PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9),
- PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84),
- PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9),
- PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1),
- PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1),
- PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb),
- PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11),
- PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6),
- PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c),
- PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e),
- PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61),
- PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517),
- PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e),
- PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb),
- PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327),
- PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947),
- PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6),
- PCMCIA_DEVICE_PROD_ID12("IC-CARD+", "IC-CARD+", 0x93693494, 0x93693494),
- PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b),
- PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0),
- PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956),
- PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616),
- PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64),
- PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5),
- PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3),
- PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2),
- PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c),
- PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40),
- PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7),
- PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab),
- PCMCIA_DEVICE_PROD_ID12("LEMEL", "LM-N89TX PRO", 0xbbefb52f, 0xd2897a97),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78),
- PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9),
- PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a),
- PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
- PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee),
- PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
- PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN10TE", 0x88fcdeda, 0xc1e2521c),
- PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
- PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
- PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307),
- PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4),
- PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8),
- PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3),
- PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c),
- PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6),
- PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472),
- PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7),
- PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9),
- PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8),
- PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76),
- PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e),
- PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f),
- PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641),
- PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b),
- PCMCIA_DEVICE_PROD_ID12("PCMCIA", " Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1),
- PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80),
- PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
- PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
- PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826),
- PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
- PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
- PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),
- PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388),
- PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c),
- PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941),
- PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265),
- PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e),
- PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8),
- PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa),
- PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f),
- PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a),
- PCMCIA_DEVICE_PROD_ID13("Hypertec", "EP401", 0x8787bec7, 0xf6e4a31e),
- PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0),
- PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e),
- PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89),
- PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
- PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
- PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
- PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
- PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
- /* too generic! */
- /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
- PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
- PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
- PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("Allied Telesis,K.K", "Ethernet LAN Card", 0x2ad62f3c, 0x9fd2f0a2, "cis/LA-PCM.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "cis/PE520.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"),
- PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b),
- PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
- 0xb4be14e3, 0x43ac239b, 0x0877b627),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
-MODULE_FIRMWARE("cis/PCMLM28.cis");
-MODULE_FIRMWARE("cis/DP83903.cis");
-MODULE_FIRMWARE("cis/LA-PCM.cis");
-MODULE_FIRMWARE("cis/PE520.cis");
-MODULE_FIRMWARE("cis/NE2K.cis");
-MODULE_FIRMWARE("cis/PE-200.cis");
-MODULE_FIRMWARE("cis/tamarack.cis");
-
-static struct pcmcia_driver pcnet_driver = {
- .name = "pcnet_cs",
- .probe = pcnet_probe,
- .remove = pcnet_detach,
- .owner = THIS_MODULE,
- .id_table = pcnet_ids,
- .suspend = pcnet_suspend,
- .resume = pcnet_resume,
-};
-module_pcmcia_driver(pcnet_driver);
diff --git a/drivers/net/ethernet/8390/stnic.c b/drivers/net/ethernet/8390/stnic.c
deleted file mode 100644
index 6cc0e190a..000000000
--- a/drivers/net/ethernet/8390/stnic.c
+++ /dev/null
@@ -1,300 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
- *
- * Copyright (C) 1999 kaz Kojima
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <mach-se/mach/se.h>
-#include <asm/machvec.h>
-#ifdef CONFIG_SH_STANDARD_BIOS
-#include <asm/sh_bios.h>
-#endif
-
-#include "8390.h"
-
-#define DRV_NAME "stnic"
-
-#define byte unsigned char
-#define half unsigned short
-#define word unsigned int
-#define vbyte volatile unsigned char
-#define vhalf volatile unsigned short
-#define vword volatile unsigned int
-
-#define STNIC_RUN 0x01 /* 1 == Run, 0 == reset. */
-
-#define START_PG 0 /* First page of TX buffer */
-#define STOP_PG 128 /* Last page +1 of RX ring */
-
-/* Alias */
-#define STNIC_CR E8390_CMD
-#define PG0_RSAR0 EN0_RSARLO
-#define PG0_RSAR1 EN0_RSARHI
-#define PG0_RBCR0 EN0_RCNTLO
-#define PG0_RBCR1 EN0_RCNTHI
-
-#define CR_RRD E8390_RREAD
-#define CR_RWR E8390_RWRITE
-#define CR_PG0 E8390_PAGE0
-#define CR_STA E8390_START
-#define CR_RDMA E8390_NODMA
-
-/* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS. */
-static byte stnic_eadr[6] =
-{0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07};
-
-static struct net_device *stnic_dev;
-
-static void stnic_reset (struct net_device *dev);
-static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
- int ring_page);
-static void stnic_block_input (struct net_device *dev, int count,
- struct sk_buff *skb , int ring_offset);
-static void stnic_block_output (struct net_device *dev, int count,
- const unsigned char *buf, int start_page);
-
-static void stnic_init (struct net_device *dev);
-
-static u32 stnic_msg_enable;
-
-module_param_named(msg_enable, stnic_msg_enable, uint, 0444);
-MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
-
-/* SH7750 specific read/write io. */
-static inline void
-STNIC_DELAY (void)
-{
- vword trash;
- trash = *(vword *) 0xa0000000;
- trash = *(vword *) 0xa0000000;
- trash = *(vword *) 0xa0000000;
-}
-
-static inline byte
-STNIC_READ (int reg)
-{
- byte val;
-
- val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff;
- STNIC_DELAY ();
- return val;
-}
-
-static inline void
-STNIC_WRITE (int reg, byte val)
-{
- *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8);
- STNIC_DELAY ();
-}
-
-static int __init stnic_probe(void)
-{
- struct net_device *dev;
- struct ei_device *ei_local;
- int err;
-
- /* If we are not running on a SolutionEngine, give up now */
- if (! MACH_SE)
- return -ENODEV;
-
- /* New style probing API */
- dev = alloc_ei_netdev();
- if (!dev)
- return -ENOMEM;
-
-#ifdef CONFIG_SH_STANDARD_BIOS
- sh_bios_get_node_addr (stnic_eadr);
-#endif
- eth_hw_addr_set(dev, stnic_eadr);
-
- /* Set the base address to point to the NIC, not the "real" base! */
- dev->base_addr = 0x1000;
- dev->irq = IRQ_STNIC;
- dev->netdev_ops = &ei_netdev_ops;
-
- /* Snarf the interrupt now. There's no point in waiting since we cannot
- share and the board will usually be enabled. */
- err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);
- if (err) {
- netdev_emerg(dev, " unable to get IRQ %d.\n", dev->irq);
- free_netdev(dev);
- return err;
- }
-
- ei_status.name = dev->name;
- ei_status.word16 = 1;
-#ifdef __LITTLE_ENDIAN__
- ei_status.bigendian = 0;
-#else
- ei_status.bigendian = 1;
-#endif
- ei_status.tx_start_page = START_PG;
- ei_status.rx_start_page = START_PG + TX_PAGES;
- ei_status.stop_page = STOP_PG;
-
- ei_status.reset_8390 = &stnic_reset;
- ei_status.get_8390_hdr = &stnic_get_hdr;
- ei_status.block_input = &stnic_block_input;
- ei_status.block_output = &stnic_block_output;
-
- stnic_init (dev);
- ei_local = netdev_priv(dev);
- ei_local->msg_enable = stnic_msg_enable;
-
- err = register_netdev(dev);
- if (err) {
- free_irq(dev->irq, dev);
- free_netdev(dev);
- return err;
- }
- stnic_dev = dev;
-
- netdev_info(dev, "NS ST-NIC 83902A\n");
-
- return 0;
-}
-
-static void
-stnic_reset (struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- *(vhalf *) PA_83902_RST = 0;
- udelay (5);
- netif_warn(ei_local, hw, dev, "8390 reset done (%ld).\n", jiffies);
- *(vhalf *) PA_83902_RST = ~0;
- udelay (5);
-}
-
-static void
-stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
- int ring_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- half buf[2];
-
- STNIC_WRITE (PG0_RSAR0, 0);
- STNIC_WRITE (PG0_RSAR1, ring_page);
- STNIC_WRITE (PG0_RBCR0, 4);
- STNIC_WRITE (PG0_RBCR1, 0);
- STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
-
- buf[0] = *(vhalf *) PA_83902_IF;
- STNIC_DELAY ();
- buf[1] = *(vhalf *) PA_83902_IF;
- STNIC_DELAY ();
- hdr->next = buf[0] >> 8;
- hdr->status = buf[0] & 0xff;
-#ifdef __LITTLE_ENDIAN__
- hdr->count = buf[1];
-#else
- hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);
-#endif
-
- netif_dbg(ei_local, probe, dev, "ring %x status %02x next %02x count %04x.\n",
- ring_page, hdr->status, hdr->next, hdr->count);
-
- STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
-}
-
-/* Block input and output, similar to the Crynwr packet driver. If you are
- porting to a new ethercard look at the packet driver source for hints.
- The HP LAN doesn't use shared memory -- we put the packet
- out through the "remote DMA" dataport. */
-
-static void
-stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb,
- int offset)
-{
- char *buf = skb->data;
- half val;
-
- STNIC_WRITE (PG0_RSAR0, offset & 0xff);
- STNIC_WRITE (PG0_RSAR1, offset >> 8);
- STNIC_WRITE (PG0_RBCR0, length & 0xff);
- STNIC_WRITE (PG0_RBCR1, length >> 8);
- STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
-
- if (length & 1)
- length++;
-
- while (length > 0)
- {
- val = *(vhalf *) PA_83902_IF;
-#ifdef __LITTLE_ENDIAN__
- *buf++ = val & 0xff;
- *buf++ = val >> 8;
-#else
- *buf++ = val >> 8;
- *buf++ = val & 0xff;
-#endif
- STNIC_DELAY ();
- length -= sizeof (half);
- }
-
- STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
-}
-
-static void
-stnic_block_output (struct net_device *dev, int length,
- const unsigned char *buf, int output_page)
-{
- STNIC_WRITE (PG0_RBCR0, 1); /* Write non-zero value */
- STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
- STNIC_DELAY ();
-
- STNIC_WRITE (PG0_RBCR0, length & 0xff);
- STNIC_WRITE (PG0_RBCR1, length >> 8);
- STNIC_WRITE (PG0_RSAR0, 0);
- STNIC_WRITE (PG0_RSAR1, output_page);
- STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA);
-
- if (length & 1)
- length++;
-
- while (length > 0)
- {
-#ifdef __LITTLE_ENDIAN__
- *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0];
-#else
- *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1];
-#endif
- STNIC_DELAY ();
- buf += sizeof (half);
- length -= sizeof (half);
- }
-
- STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
-}
-
-/* This function resets the STNIC if something screws up. */
-static void
-stnic_init (struct net_device *dev)
-{
- stnic_reset (dev);
- NS8390_init (dev, 0);
-}
-
-static void __exit stnic_cleanup(void)
-{
- unregister_netdev(stnic_dev);
- free_irq(stnic_dev->irq, stnic_dev);
- free_netdev(stnic_dev);
-}
-
-module_init(stnic_probe);
-module_exit(stnic_cleanup);
-MODULE_DESCRIPTION("National Semiconductor DP83902AV ethernet driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/8390/xsurf100.c b/drivers/net/ethernet/8390/xsurf100.c
deleted file mode 100644
index fe7a74707..000000000
--- a/drivers/net/ethernet/8390/xsurf100.c
+++ /dev/null
@@ -1,377 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/platform_device.h>
-#include <linux/zorro.h>
-#include <net/ax88796.h>
-#include <asm/amigaints.h>
-
-#define ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF100 \
- ZORRO_ID(INDIVIDUAL_COMPUTERS, 0x64, 0)
-
-#define XS100_IRQSTATUS_BASE 0x40
-#define XS100_8390_BASE 0x800
-
-/* Longword-access area. Translated to 2 16-bit access cycles by the
- * X-Surf 100 FPGA
- */
-#define XS100_8390_DATA32_BASE 0x8000
-#define XS100_8390_DATA32_SIZE 0x2000
-/* Sub-Areas for fast data register access; addresses relative to area begin */
-#define XS100_8390_DATA_READ32_BASE 0x0880
-#define XS100_8390_DATA_WRITE32_BASE 0x0C80
-#define XS100_8390_DATA_AREA_SIZE 0x80
-
-/* force unsigned long back to 'void __iomem *' */
-#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
-
-#define ei_inb(_a) z_readb(ax_convert_addr(_a))
-#define ei_outb(_v, _a) z_writeb(_v, ax_convert_addr(_a))
-
-#define ei_inw(_a) z_readw(ax_convert_addr(_a))
-#define ei_outw(_v, _a) z_writew(_v, ax_convert_addr(_a))
-
-#define ei_inb_p(_a) ei_inb(_a)
-#define ei_outb_p(_v, _a) ei_outb(_v, _a)
-
-/* define EI_SHIFT() to take into account our register offsets */
-#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
-
-/* Ensure we have our RCR base value */
-#define AX88796_PLATFORM
-
-#include "8390.h"
-
-/* from ne.c */
-#define NE_CMD EI_SHIFT(0x00)
-#define NE_RESET EI_SHIFT(0x1f)
-#define NE_DATAPORT EI_SHIFT(0x10)
-
-struct xsurf100_ax_plat_data {
- struct ax_plat_data ax;
- void __iomem *base_regs;
- void __iomem *data_area;
-};
-
-static int is_xsurf100_network_irq(struct platform_device *pdev)
-{
- struct xsurf100_ax_plat_data *xs100 = dev_get_platdata(&pdev->dev);
-
- return (readw(xs100->base_regs + XS100_IRQSTATUS_BASE) & 0xaaaa) != 0;
-}
-
-/* These functions guarantee that the iomem is accessed with 32 bit
- * cycles only. z_memcpy_fromio / z_memcpy_toio don't
- */
-static void z_memcpy_fromio32(void *dst, const void __iomem *src, size_t bytes)
-{
- while (bytes > 32) {
- asm __volatile__
- ("movem.l (%0)+,%%d0-%%d7\n"
- "movem.l %%d0-%%d7,(%1)\n"
- "adda.l #32,%1" : "=a"(src), "=a"(dst)
- : "0"(src), "1"(dst) : "d0", "d1", "d2", "d3", "d4",
- "d5", "d6", "d7", "memory");
- bytes -= 32;
- }
- while (bytes) {
- *(uint32_t *)dst = z_readl(src);
- src += 4;
- dst += 4;
- bytes -= 4;
- }
-}
-
-static void z_memcpy_toio32(void __iomem *dst, const void *src, size_t bytes)
-{
- while (bytes) {
- z_writel(*(const uint32_t *)src, dst);
- src += 4;
- dst += 4;
- bytes -= 4;
- }
-}
-
-static void xs100_write(struct net_device *dev, const void *src,
- unsigned int count)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- struct platform_device *pdev = to_platform_device(dev->dev.parent);
- struct xsurf100_ax_plat_data *xs100 = dev_get_platdata(&pdev->dev);
-
- /* copy whole blocks */
- while (count > XS100_8390_DATA_AREA_SIZE) {
- z_memcpy_toio32(xs100->data_area +
- XS100_8390_DATA_WRITE32_BASE, src,
- XS100_8390_DATA_AREA_SIZE);
- src += XS100_8390_DATA_AREA_SIZE;
- count -= XS100_8390_DATA_AREA_SIZE;
- }
- /* copy whole dwords */
- z_memcpy_toio32(xs100->data_area + XS100_8390_DATA_WRITE32_BASE,
- src, count & ~3);
- src += count & ~3;
- if (count & 2) {
- ei_outw(*(uint16_t *)src, ei_local->mem + NE_DATAPORT);
- src += 2;
- }
- if (count & 1)
- ei_outb(*(uint8_t *)src, ei_local->mem + NE_DATAPORT);
-}
-
-static void xs100_read(struct net_device *dev, void *dst, unsigned int count)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- struct platform_device *pdev = to_platform_device(dev->dev.parent);
- struct xsurf100_ax_plat_data *xs100 = dev_get_platdata(&pdev->dev);
-
- /* copy whole blocks */
- while (count > XS100_8390_DATA_AREA_SIZE) {
- z_memcpy_fromio32(dst, xs100->data_area +
- XS100_8390_DATA_READ32_BASE,
- XS100_8390_DATA_AREA_SIZE);
- dst += XS100_8390_DATA_AREA_SIZE;
- count -= XS100_8390_DATA_AREA_SIZE;
- }
- /* copy whole dwords */
- z_memcpy_fromio32(dst, xs100->data_area + XS100_8390_DATA_READ32_BASE,
- count & ~3);
- dst += count & ~3;
- if (count & 2) {
- *(uint16_t *)dst = ei_inw(ei_local->mem + NE_DATAPORT);
- dst += 2;
- }
- if (count & 1)
- *(uint8_t *)dst = ei_inb(ei_local->mem + NE_DATAPORT);
-}
-
-/* Block input and output, similar to the Crynwr packet driver. If
- * you are porting to a new ethercard, look at the packet driver
- * source for hints. The NEx000 doesn't share the on-board packet
- * memory -- you have to put the packet out through the "remote DMA"
- * dataport using ei_outb.
- */
-static void xs100_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *nic_base = ei_local->mem;
- char *buf = skb->data;
-
- if (ei_local->dmaing) {
- netdev_err(dev,
- "DMAing conflict in %s [DMAstat:%d][irqlock:%d]\n",
- __func__,
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing |= 0x01;
-
- ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
- ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
- ei_outb(count >> 8, nic_base + EN0_RCNTHI);
- ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
- ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
- ei_outb(E8390_RREAD + E8390_START, nic_base + NE_CMD);
-
- xs100_read(dev, buf, count);
-
- ei_local->dmaing &= ~1;
-}
-
-static void xs100_block_output(struct net_device *dev, int count,
- const unsigned char *buf, const int start_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *nic_base = ei_local->mem;
- unsigned long dma_start;
-
- /* Round the count up for word writes. Do we need to do this?
- * What effect will an odd byte count have on the 8390? I
- * should check someday.
- */
- if (ei_local->word16 && (count & 0x01))
- count++;
-
- /* This *shouldn't* happen. If it does, it's the last thing
- * you'll see
- */
- if (ei_local->dmaing) {
- netdev_err(dev,
- "DMAing conflict in %s [DMAstat:%d][irqlock:%d]\n",
- __func__,
- ei_local->dmaing, ei_local->irqlock);
- return;
- }
-
- ei_local->dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- ei_outb(E8390_PAGE0 + E8390_START + E8390_NODMA, nic_base + NE_CMD);
-
- ei_outb(ENISR_RDC, nic_base + EN0_ISR);
-
- /* Now the normal output. */
- ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
- ei_outb(count >> 8, nic_base + EN0_RCNTHI);
- ei_outb(0x00, nic_base + EN0_RSARLO);
- ei_outb(start_page, nic_base + EN0_RSARHI);
-
- ei_outb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);
-
- xs100_write(dev, buf, count);
-
- dma_start = jiffies;
-
- while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
- if (jiffies - dma_start > 2 * HZ / 100) { /* 20ms */
- netdev_warn(dev, "timeout waiting for Tx RDC.\n");
- ei_local->reset_8390(dev);
- ax_NS8390_reinit(dev);
- break;
- }
- }
-
- ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_local->dmaing &= ~0x01;
-}
-
-static int xsurf100_probe(struct zorro_dev *zdev,
- const struct zorro_device_id *ent)
-{
- struct platform_device *pdev;
- struct xsurf100_ax_plat_data ax88796_data;
- struct resource res[2] = {
- DEFINE_RES_NAMED(IRQ_AMIGA_PORTS, 1, NULL,
- IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE),
- DEFINE_RES_MEM(zdev->resource.start + XS100_8390_BASE,
- 4 * 0x20)
- };
- int reg;
- /* This table is referenced in the device structure, so it must
- * outlive the scope of xsurf100_probe.
- */
- static u32 reg_offsets[32];
- int ret = 0;
-
- /* X-Surf 100 control and 32 bit ring buffer data access areas.
- * These resources are not used by the ax88796 driver, so must
- * be requested here and passed via platform data.
- */
-
- if (!request_mem_region(zdev->resource.start, 0x100, zdev->name)) {
- dev_err(&zdev->dev, "cannot reserve X-Surf 100 control registers\n");
- return -ENXIO;
- }
-
- if (!request_mem_region(zdev->resource.start +
- XS100_8390_DATA32_BASE,
- XS100_8390_DATA32_SIZE,
- "X-Surf 100 32-bit data access")) {
- dev_err(&zdev->dev, "cannot reserve 32-bit area\n");
- ret = -ENXIO;
- goto exit_req;
- }
-
- for (reg = 0; reg < 0x20; reg++)
- reg_offsets[reg] = 4 * reg;
-
- memset(&ax88796_data, 0, sizeof(ax88796_data));
- ax88796_data.ax.flags = AXFLG_HAS_EEPROM;
- ax88796_data.ax.wordlength = 2;
- ax88796_data.ax.dcr_val = 0x48;
- ax88796_data.ax.rcr_val = 0x40;
- ax88796_data.ax.reg_offsets = reg_offsets;
- ax88796_data.ax.check_irq = is_xsurf100_network_irq;
- ax88796_data.base_regs = ioremap(zdev->resource.start, 0x100);
-
- /* error handling for ioremap regs */
- if (!ax88796_data.base_regs) {
- dev_err(&zdev->dev, "Cannot ioremap area %pR (registers)\n",
- &zdev->resource);
-
- ret = -ENXIO;
- goto exit_req2;
- }
-
- ax88796_data.data_area = ioremap(zdev->resource.start +
- XS100_8390_DATA32_BASE, XS100_8390_DATA32_SIZE);
-
- /* error handling for ioremap data */
- if (!ax88796_data.data_area) {
- dev_err(&zdev->dev,
- "Cannot ioremap area %pR offset %x (32-bit access)\n",
- &zdev->resource, XS100_8390_DATA32_BASE);
-
- ret = -ENXIO;
- goto exit_mem;
- }
-
- ax88796_data.ax.block_output = xs100_block_output;
- ax88796_data.ax.block_input = xs100_block_input;
-
- pdev = platform_device_register_resndata(&zdev->dev, "ax88796",
- zdev->slotaddr, res, 2,
- &ax88796_data,
- sizeof(ax88796_data));
-
- if (IS_ERR(pdev)) {
- dev_err(&zdev->dev, "cannot register platform device\n");
- ret = -ENXIO;
- goto exit_mem2;
- }
-
- zorro_set_drvdata(zdev, pdev);
-
- if (!ret)
- return 0;
-
- exit_mem2:
- iounmap(ax88796_data.data_area);
-
- exit_mem:
- iounmap(ax88796_data.base_regs);
-
- exit_req2:
- release_mem_region(zdev->resource.start + XS100_8390_DATA32_BASE,
- XS100_8390_DATA32_SIZE);
-
- exit_req:
- release_mem_region(zdev->resource.start, 0x100);
-
- return ret;
-}
-
-static void xsurf100_remove(struct zorro_dev *zdev)
-{
- struct platform_device *pdev = zorro_get_drvdata(zdev);
- struct xsurf100_ax_plat_data *xs100 = dev_get_platdata(&pdev->dev);
-
- platform_device_unregister(pdev);
-
- iounmap(xs100->base_regs);
- release_mem_region(zdev->resource.start, 0x100);
- iounmap(xs100->data_area);
- release_mem_region(zdev->resource.start + XS100_8390_DATA32_BASE,
- XS100_8390_DATA32_SIZE);
-}
-
-static const struct zorro_device_id xsurf100_zorro_tbl[] = {
- { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF100, },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(zorro, xsurf100_zorro_tbl);
-
-static struct zorro_driver xsurf100_driver = {
- .name = "xsurf100",
- .id_table = xsurf100_zorro_tbl,
- .probe = xsurf100_probe,
- .remove = xsurf100_remove,
-};
-
-module_driver(xsurf100_driver, zorro_register_driver, zorro_unregister_driver);
-
-MODULE_DESCRIPTION("X-Surf 100 driver");
-MODULE_AUTHOR("Michael Karcher <kernel@mkarcher.dialup.fu-berlin.de>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
deleted file mode 100644
index c24dd4fe7..000000000
--- a/drivers/net/ethernet/8390/zorro8390.c
+++ /dev/null
@@ -1,447 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Amiga Linux/m68k and Linux/PPC Zorro NS8390 Ethernet Driver
- *
- * (C) Copyright 1998-2000 by some Elitist 680x0 Users(TM)
- *
- * ---------------------------------------------------------------------------
- *
- * This program is based on all the other NE2000 drivers for Linux
- *
- * ---------------------------------------------------------------------------
- *
- * The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS
- * Ethernet Controllers.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/zorro.h>
-#include <linux/jiffies.h>
-
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-#define ei_inb(port) in_8(port)
-#define ei_outb(val, port) out_8(port, val)
-#define ei_inb_p(port) in_8(port)
-#define ei_outb_p(val, port) out_8(port, val)
-
-static const char version[] =
- "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-#define DRV_NAME "zorro8390"
-
-#define NE_BASE (dev->base_addr)
-#define NE_CMD (0x00 * 2)
-#define NE_DATAPORT (0x10 * 2) /* NatSemi-defined port window offset */
-#define NE_RESET (0x1f * 2) /* Issue a read to reset,
- * a write to clear. */
-#define NE_IO_EXTENT (0x20 * 2)
-
-#define NE_EN0_ISR (0x07 * 2)
-#define NE_EN0_DCFG (0x0e * 2)
-
-#define NE_EN0_RSARLO (0x08 * 2)
-#define NE_EN0_RSARHI (0x09 * 2)
-#define NE_EN0_RCNTLO (0x0a * 2)
-#define NE_EN0_RXCR (0x0c * 2)
-#define NE_EN0_TXCR (0x0d * 2)
-#define NE_EN0_RCNTHI (0x0b * 2)
-#define NE_EN0_IMR (0x0f * 2)
-
-#define NESM_START_PG 0x40 /* First page of TX buffer */
-#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-#define WORDSWAP(a) ((((a) >> 8) & 0xff) | ((a) << 8))
-
-static struct card_info {
- zorro_id id;
- const char *name;
- unsigned int offset;
-} cards[] = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
- { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
-};
-
-/* Hard reset the card. This used to pause for the same period that a
- * 8390 reset command required, but that shouldn't be necessary.
- */
-static void zorro8390_reset_8390(struct net_device *dev)
-{
- unsigned long reset_start_time = jiffies;
- struct ei_device *ei_local = netdev_priv(dev);
-
- netif_dbg(ei_local, hw, dev, "resetting - t=%ld...\n", jiffies);
-
- z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
- ei_status.txing = 0;
- ei_status.dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
- netdev_warn(dev, "%s: did not complete\n", __func__);
- break;
- }
- z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR); /* Ack intr */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- * we don't need to be concerned with ring wrap as the header will be at
- * the start of a page, so we optimize accordingly.
- */
-static void zorro8390_get_8390_hdr(struct net_device *dev,
- struct e8390_pkt_hdr *hdr, int ring_page)
-{
- int nic_base = dev->base_addr;
- int cnt;
- short *ptrs;
-
- /* This *shouldn't* happen.
- * If it does, it's the last thing you'll see
- */
- if (ei_status.dmaing) {
- netdev_warn(dev,
- "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
- __func__, ei_status.dmaing, ei_status.irqlock);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
- z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
- z_writeb(0, nic_base + NE_EN0_RCNTHI);
- z_writeb(0, nic_base + NE_EN0_RSARLO); /* On page boundary */
- z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
- z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- ptrs = (short *)hdr;
- for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++)
- *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
-
- hdr->count = WORDSWAP(hdr->count);
-
- ei_status.dmaing &= ~0x01;
-}
-
-/* Block input and output, similar to the Crynwr packet driver.
- * If you are porting to a new ethercard, look at the packet driver source
- * for hints. The NEx000 doesn't share the on-board packet memory --
- * you have to put the packet out through the "remote DMA" dataport
- * using z_writeb.
- */
-static void zorro8390_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset)
-{
- int nic_base = dev->base_addr;
- char *buf = skb->data;
- short *ptrs;
- int cnt;
-
- /* This *shouldn't* happen.
- * If it does, it's the last thing you'll see
- */
- if (ei_status.dmaing) {
- netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
- __func__, ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
- z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
- z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
- z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
- z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
- z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- ptrs = (short *)buf;
- for (cnt = 0; cnt < count >> 1; cnt++)
- *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
- if (count & 0x01)
- buf[count - 1] = z_readb(NE_BASE + NE_DATAPORT);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
- ei_status.dmaing &= ~0x01;
-}
-
-static void zorro8390_block_output(struct net_device *dev, int count,
- const unsigned char *buf,
- const int start_page)
-{
- int nic_base = NE_BASE;
- unsigned long dma_start;
- short *ptrs;
- int cnt;
-
- /* Round the count up for word writes. Do we need to do this?
- * What effect will an odd byte count have on the 8390?
- * I should check someday.
- */
- if (count & 0x01)
- count++;
-
- /* This *shouldn't* happen.
- * If it does, it's the last thing you'll see
- */
- if (ei_status.dmaing) {
- netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
- __func__, ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-
- /* Now the normal output. */
- z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
- z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
- z_writeb(0x00, nic_base + NE_EN0_RSARLO);
- z_writeb(start_page, nic_base + NE_EN0_RSARHI);
-
- z_writeb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);
- ptrs = (short *)buf;
- for (cnt = 0; cnt < count >> 1; cnt++)
- z_writew(*ptrs++, NE_BASE + NE_DATAPORT);
-
- dma_start = jiffies;
-
- while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2 * HZ / 100)) {
- /* 20ms */
- netdev_warn(dev, "timeout waiting for Tx RDC\n");
- zorro8390_reset_8390(dev);
- __NS8390_init(dev, 1);
- break;
- }
-
- z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr */
- ei_status.dmaing &= ~0x01;
-}
-
-static int zorro8390_open(struct net_device *dev)
-{
- __ei_open(dev);
- return 0;
-}
-
-static int zorro8390_close(struct net_device *dev)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-
- netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard\n");
- __ei_close(dev);
- return 0;
-}
-
-static void zorro8390_remove_one(struct zorro_dev *z)
-{
- struct net_device *dev = zorro_get_drvdata(z);
-
- unregister_netdev(dev);
- free_irq(IRQ_AMIGA_PORTS, dev);
- release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT * 2);
- free_netdev(dev);
-}
-
-static struct zorro_device_id zorro8390_zorro_tbl[] = {
- { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
- { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
- { 0 }
-};
-MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
-
-static const struct net_device_ops zorro8390_netdev_ops = {
- .ndo_open = zorro8390_open,
- .ndo_stop = zorro8390_close,
- .ndo_start_xmit = __ei_start_xmit,
- .ndo_tx_timeout = __ei_tx_timeout,
- .ndo_get_stats = __ei_get_stats,
- .ndo_set_rx_mode = __ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = __ei_poll,
-#endif
-};
-
-static int zorro8390_init(struct net_device *dev, unsigned long board,
- const char *name, void __iomem *ioaddr)
-{
- int i;
- int err;
- unsigned char SA_prom[32];
- int start_page, stop_page;
- static u32 zorro8390_offsets[16] = {
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
- 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
- };
-
- /* Reset card. Who knows what dain-bramaged state it was left in. */
- {
- unsigned long reset_start_time = jiffies;
-
- z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
- while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies,
- reset_start_time + 2 * HZ / 100)) {
- netdev_warn(dev, "not found (no reset ack)\n");
- return -ENODEV;
- }
-
- z_writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */
- }
-
- /* Read the 16 bytes of station address PROM.
- * We must first initialize registers,
- * similar to NS8390_init(eifdev, 0).
- * We can't reliably read the SAPROM address without this.
- * (I learned the hard way!).
- */
- {
- static const struct {
- u32 value;
- u32 offset;
- } program_seq[] = {
- {E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
- /* Select page 0 */
- {0x48, NE_EN0_DCFG}, /* 0x48: Set byte-wide access */
- {0x00, NE_EN0_RCNTLO}, /* Clear the count regs */
- {0x00, NE_EN0_RCNTHI},
- {0x00, NE_EN0_IMR}, /* Mask completion irq */
- {0xFF, NE_EN0_ISR},
- {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
- {32, NE_EN0_RCNTLO},
- {0x00, NE_EN0_RCNTHI},
- {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000 */
- {0x00, NE_EN0_RSARHI},
- {E8390_RREAD + E8390_START, NE_CMD},
- };
- for (i = 0; i < ARRAY_SIZE(program_seq); i++)
- z_writeb(program_seq[i].value,
- ioaddr + program_seq[i].offset);
- }
- for (i = 0; i < 16; i++) {
- SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
- (void)z_readb(ioaddr + NE_DATAPORT);
- }
-
- /* We must set the 8390 for word mode. */
- z_writeb(0x49, ioaddr + NE_EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
-
- dev->base_addr = (unsigned long)ioaddr;
- dev->irq = IRQ_AMIGA_PORTS;
-
- /* Install the Interrupt handler */
- i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt,
- IRQF_SHARED, DRV_NAME, dev);
- if (i)
- return i;
-
- eth_hw_addr_set(dev, SA_prom);
-
- pr_debug("Found ethernet address: %pM\n", dev->dev_addr);
-
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
- ei_status.word16 = 1;
-
- ei_status.rx_start_page = start_page + TX_PAGES;
-
- ei_status.reset_8390 = zorro8390_reset_8390;
- ei_status.block_input = zorro8390_block_input;
- ei_status.block_output = zorro8390_block_output;
- ei_status.get_8390_hdr = zorro8390_get_8390_hdr;
- ei_status.reg_offset = zorro8390_offsets;
-
- dev->netdev_ops = &zorro8390_netdev_ops;
- __NS8390_init(dev, 0);
-
- err = register_netdev(dev);
- if (err) {
- free_irq(IRQ_AMIGA_PORTS, dev);
- return err;
- }
-
- netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n",
- name, board, dev->dev_addr);
-
- return 0;
-}
-
-static int zorro8390_init_one(struct zorro_dev *z,
- const struct zorro_device_id *ent)
-{
- struct net_device *dev;
- unsigned long board, ioaddr;
- int err, i;
-
- for (i = ARRAY_SIZE(cards) - 1; i >= 0; i--)
- if (z->id == cards[i].id)
- break;
- if (i < 0)
- return -ENODEV;
-
- board = z->resource.start;
- ioaddr = board + cards[i].offset;
- dev = ____alloc_ei_netdev(0);
- if (!dev)
- return -ENOMEM;
- if (!request_mem_region(ioaddr, NE_IO_EXTENT * 2, DRV_NAME)) {
- free_netdev(dev);
- return -EBUSY;
- }
- err = zorro8390_init(dev, board, cards[i].name, ZTWO_VADDR(ioaddr));
- if (err) {
- release_mem_region(ioaddr, NE_IO_EXTENT * 2);
- free_netdev(dev);
- return err;
- }
- zorro_set_drvdata(z, dev);
- return 0;
-}
-
-static struct zorro_driver zorro8390_driver = {
- .name = "zorro8390",
- .id_table = zorro8390_zorro_tbl,
- .probe = zorro8390_init_one,
- .remove = zorro8390_remove_one,
-};
-
-static int __init zorro8390_init_module(void)
-{
- return zorro_register_driver(&zorro8390_driver);
-}
-
-static void __exit zorro8390_cleanup_module(void)
-{
- zorro_unregister_driver(&zorro8390_driver);
-}
-
-module_init(zorro8390_init_module);
-module_exit(zorro8390_cleanup_module);
-
-MODULE_DESCRIPTION("Zorro NS8390-based ethernet driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index 36a18d958..6eb89c305 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_FB_SBUS) += sbuslib.o
obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
# Hardware specific drivers go first
-obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
+# obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711x-fb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
@@ -53,13 +53,13 @@ obj-$(CONFIG_FB_CG14) += cg14.o
obj-$(CONFIG_FB_P9100) += p9100.o
obj-$(CONFIG_FB_TCX) += tcx.o
obj-$(CONFIG_FB_LEO) += leo.o
-obj-$(CONFIG_FB_ACORN) += acornfb.o
-obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
+# obj-$(CONFIG_FB_ACORN) += acornfb.o
+# obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
obj-$(CONFIG_FB_MAC) += macfb.o
obj-$(CONFIG_FB_HECUBA) += hecubafb.o
obj-$(CONFIG_FB_N411) += n411.o
-obj-$(CONFIG_FB_HGA) += hgafb.o
+# obj-$(CONFIG_FB_HGA) += hgafb.o
obj-$(CONFIG_FB_XVR500) += sunxvr500.o
obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o
obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o
@@ -118,7 +118,7 @@ obj-$(CONFIG_FB_SM712) += sm712fb.o
obj-$(CONFIG_FB_UVESA) += uvesafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o
obj-$(CONFIG_FB_EFI) += efifb.o
-obj-$(CONFIG_FB_VGA16) += vga16fb.o
+# obj-$(CONFIG_FB_VGA16) += vga16fb.o
obj-$(CONFIG_FB_OF) += offb.o
obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o
obj-$(CONFIG_FB_SIMPLE) += simplefb.o
diff --git a/drivers/video/fbdev/acornfb.c b/drivers/video/fbdev/acornfb.c
deleted file mode 100644
index f0600f6ca..000000000
--- a/drivers/video/fbdev/acornfb.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/drivers/video/acornfb.c
- *
- * Copyright (C) 1998-2001 Russell King
- *
- * Frame buffer code for Acorn platforms
- *
- * NOTE: Most of the modes with X!=640 will disappear shortly.
- * NOTE: Startup setting of HS & VS polarity not supported.
- * (do we need to support it if we're coming up in 640x480?)
- *
- * FIXME: (things broken by the "new improved" FBCON API)
- * - Blanking 8bpp displays with VIDC
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/fb.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/gfp.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include "acornfb.h"
-
-/*
- * Default resolution.
- * NOTE that it has to be supported in the table towards
- * the end of this file.
- */
-#define DEFAULT_XRES 640
-#define DEFAULT_YRES 480
-#define DEFAULT_BPP 4
-
-/*
- * define this to debug the video mode selection
- */
-#undef DEBUG_MODE_SELECTION
-
-/*
- * Translation from RISC OS monitor types to actual
- * HSYNC and VSYNC frequency ranges. These are
- * probably not right, but they're the best info I
- * have. Allow 1% either way on the nominal for TVs.
- */
-#define NR_MONTYPES 6
-static struct fb_monspecs monspecs[NR_MONTYPES] = {
- { /* TV */
- .hfmin = 15469,
- .hfmax = 15781,
- .vfmin = 49,
- .vfmax = 51,
- }, { /* Multi Freq */
- .hfmin = 0,
- .hfmax = 99999,
- .vfmin = 0,
- .vfmax = 199,
- }, { /* Hi-res mono */
- .hfmin = 58608,
- .hfmax = 58608,
- .vfmin = 64,
- .vfmax = 64,
- }, { /* VGA */
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- }, { /* SVGA */
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 56,
- .vfmax = 75,
- }, {
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- }
-};
-
-static struct fb_info fb_info;
-static struct acornfb_par current_par;
-static struct vidc_timing current_vidc;
-
-extern unsigned int vram_size; /* set by setup.c */
-
-#ifdef HAS_VIDC20
-#include <mach/acornfb.h>
-
-#define MAX_SIZE (2*1024*1024)
-
-/* VIDC20 has a different set of rules from the VIDC:
- * hcr : must be multiple of 4
- * hswr : must be even
- * hdsr : must be even
- * hder : must be even
- * vcr : >= 2, (interlace, must be odd)
- * vswr : >= 1
- * vdsr : >= 1
- * vder : >= vdsr
- */
-static void acornfb_set_timing(struct fb_info *info)
-{
- struct fb_var_screeninfo *var = &info->var;
- struct vidc_timing vidc;
- u_int vcr, fsize;
- u_int ext_ctl, dat_ctl;
- u_int words_per_line;
-
- memset(&vidc, 0, sizeof(vidc));
-
- vidc.h_sync_width = var->hsync_len - 8;
- vidc.h_border_start = vidc.h_sync_width + var->left_margin + 8 - 12;
- vidc.h_display_start = vidc.h_border_start + 12 - 18;
- vidc.h_display_end = vidc.h_display_start + var->xres;
- vidc.h_border_end = vidc.h_display_end + 18 - 12;
- vidc.h_cycle = vidc.h_border_end + var->right_margin + 12 - 8;
- vidc.h_interlace = vidc.h_cycle / 2;
- vidc.v_sync_width = var->vsync_len - 1;
- vidc.v_border_start = vidc.v_sync_width + var->upper_margin;
- vidc.v_display_start = vidc.v_border_start;
- vidc.v_display_end = vidc.v_display_start + var->yres;
- vidc.v_border_end = vidc.v_display_end;
- vidc.control = acornfb_default_control();
-
- vcr = var->vsync_len + var->upper_margin + var->yres +
- var->lower_margin;
-
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- vidc.v_cycle = (vcr - 3) / 2;
- vidc.control |= VIDC20_CTRL_INT;
- } else
- vidc.v_cycle = vcr - 2;
-
- switch (var->bits_per_pixel) {
- case 1: vidc.control |= VIDC20_CTRL_1BPP; break;
- case 2: vidc.control |= VIDC20_CTRL_2BPP; break;
- case 4: vidc.control |= VIDC20_CTRL_4BPP; break;
- default:
- case 8: vidc.control |= VIDC20_CTRL_8BPP; break;
- case 16: vidc.control |= VIDC20_CTRL_16BPP; break;
- case 32: vidc.control |= VIDC20_CTRL_32BPP; break;
- }
-
- acornfb_vidc20_find_rates(&vidc, var);
- fsize = var->vsync_len + var->upper_margin + var->lower_margin - 1;
-
- if (memcmp(¤t_vidc, &vidc, sizeof(vidc))) {
- current_vidc = vidc;
-
- vidc_writel(VIDC20_CTRL | vidc.control);
- vidc_writel(0xd0000000 | vidc.pll_ctl);
- vidc_writel(0x80000000 | vidc.h_cycle);
- vidc_writel(0x81000000 | vidc.h_sync_width);
- vidc_writel(0x82000000 | vidc.h_border_start);
- vidc_writel(0x83000000 | vidc.h_display_start);
- vidc_writel(0x84000000 | vidc.h_display_end);
- vidc_writel(0x85000000 | vidc.h_border_end);
- vidc_writel(0x86000000);
- vidc_writel(0x87000000 | vidc.h_interlace);
- vidc_writel(0x90000000 | vidc.v_cycle);
- vidc_writel(0x91000000 | vidc.v_sync_width);
- vidc_writel(0x92000000 | vidc.v_border_start);
- vidc_writel(0x93000000 | vidc.v_display_start);
- vidc_writel(0x94000000 | vidc.v_display_end);
- vidc_writel(0x95000000 | vidc.v_border_end);
- vidc_writel(0x96000000);
- vidc_writel(0x97000000);
- }
-
- iomd_writel(fsize, IOMD_FSIZE);
-
- ext_ctl = acornfb_default_econtrol();
-
- if (var->sync & FB_SYNC_COMP_HIGH_ACT) /* should be FB_SYNC_COMP */
- ext_ctl |= VIDC20_ECTL_HS_NCSYNC | VIDC20_ECTL_VS_NCSYNC;
- else {
- if (var->sync & FB_SYNC_HOR_HIGH_ACT)
- ext_ctl |= VIDC20_ECTL_HS_HSYNC;
- else
- ext_ctl |= VIDC20_ECTL_HS_NHSYNC;
-
- if (var->sync & FB_SYNC_VERT_HIGH_ACT)
- ext_ctl |= VIDC20_ECTL_VS_VSYNC;
- else
- ext_ctl |= VIDC20_ECTL_VS_NVSYNC;
- }
-
- vidc_writel(VIDC20_ECTL | ext_ctl);
-
- words_per_line = var->xres * var->bits_per_pixel / 32;
-
- if (current_par.using_vram && info->fix.smem_len == 2048*1024)
- words_per_line /= 2;
-
- /* RiscPC doesn't use the VIDC's VRAM control. */
- dat_ctl = VIDC20_DCTL_VRAM_DIS | VIDC20_DCTL_SNA | words_per_line;
-
- /* The data bus width is dependent on both the type
- * and amount of video memory.
- * DRAM 32bit low
- * 1MB VRAM 32bit
- * 2MB VRAM 64bit
- */
- if (current_par.using_vram && current_par.vram_half_sam == 2048)
- dat_ctl |= VIDC20_DCTL_BUS_D63_0;
- else
- dat_ctl |= VIDC20_DCTL_BUS_D31_0;
-
- vidc_writel(VIDC20_DCTL | dat_ctl);
-
-#ifdef DEBUG_MODE_SELECTION
- printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
- var->yres, var->bits_per_pixel);
- printk(KERN_DEBUG " H-cycle : %d\n", vidc.h_cycle);
- printk(KERN_DEBUG " H-sync-width : %d\n", vidc.h_sync_width);
- printk(KERN_DEBUG " H-border-start : %d\n", vidc.h_border_start);
- printk(KERN_DEBUG " H-display-start : %d\n", vidc.h_display_start);
- printk(KERN_DEBUG " H-display-end : %d\n", vidc.h_display_end);
- printk(KERN_DEBUG " H-border-end : %d\n", vidc.h_border_end);
- printk(KERN_DEBUG " H-interlace : %d\n", vidc.h_interlace);
- printk(KERN_DEBUG " V-cycle : %d\n", vidc.v_cycle);
- printk(KERN_DEBUG " V-sync-width : %d\n", vidc.v_sync_width);
- printk(KERN_DEBUG " V-border-start : %d\n", vidc.v_border_start);
- printk(KERN_DEBUG " V-display-start : %d\n", vidc.v_display_start);
- printk(KERN_DEBUG " V-display-end : %d\n", vidc.v_display_end);
- printk(KERN_DEBUG " V-border-end : %d\n", vidc.v_border_end);
- printk(KERN_DEBUG " Ext Ctrl (C) : 0x%08X\n", ext_ctl);
- printk(KERN_DEBUG " PLL Ctrl (D) : 0x%08X\n", vidc.pll_ctl);
- printk(KERN_DEBUG " Ctrl (E) : 0x%08X\n", vidc.control);
- printk(KERN_DEBUG " Data Ctrl (F) : 0x%08X\n", dat_ctl);
- printk(KERN_DEBUG " Fsize : 0x%08X\n", fsize);
-#endif
-}
-
-/*
- * We have to take note of the VIDC20's 16-bit palette here.
- * The VIDC20 looks up a 16 bit pixel as follows:
- *
- * bits 111111
- * 5432109876543210
- * red ++++++++ (8 bits, 7 to 0)
- * green ++++++++ (8 bits, 11 to 4)
- * blue ++++++++ (8 bits, 15 to 8)
- *
- * We use a pixel which looks like:
- *
- * bits 111111
- * 5432109876543210
- * red +++++ (5 bits, 4 to 0)
- * green +++++ (5 bits, 9 to 5)
- * blue +++++ (5 bits, 14 to 10)
- */
-static int
-acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int trans, struct fb_info *info)
-{
- union palette pal;
-
- if (regno >= current_par.palette_size)
- return 1;
-
- if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
- u32 pseudo_val;
-
- pseudo_val = regno << info->var.red.offset;
- pseudo_val |= regno << info->var.green.offset;
- pseudo_val |= regno << info->var.blue.offset;
-
- ((u32 *)info->pseudo_palette)[regno] = pseudo_val;
- }
-
- pal.p = 0;
- pal.vidc20.red = red >> 8;
- pal.vidc20.green = green >> 8;
- pal.vidc20.blue = blue >> 8;
-
- current_par.palette[regno] = pal;
-
- if (info->var.bits_per_pixel == 16) {
- int i;
-
- pal.p = 0;
- vidc_writel(0x10000000);
- for (i = 0; i < 256; i += 1) {
- pal.vidc20.red = current_par.palette[i & 31].vidc20.red;
- pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
- pal.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
- vidc_writel(pal.p);
- /* Palette register pointer auto-increments */
- }
- } else {
- vidc_writel(0x10000000 | regno);
- vidc_writel(pal.p);
- }
-
- return 0;
-}
-#endif
-
-/*
- * Before selecting the timing parameters, adjust
- * the resolution to fit the rules.
- */
-static int
-acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, u_int fontht)
-{
- u_int font_line_len, sam_size, min_size, size, nr_y;
-
- /* xres must be even */
- var->xres = (var->xres + 1) & ~1;
-
- /*
- * We don't allow xres_virtual to differ from xres
- */
- var->xres_virtual = var->xres;
- var->xoffset = 0;
-
- if (current_par.using_vram)
- sam_size = current_par.vram_half_sam * 2;
- else
- sam_size = 16;
-
- /*
- * Now, find a value for yres_virtual which allows
- * us to do ywrap scrolling. The value of
- * yres_virtual must be such that the end of the
- * displayable frame buffer must be aligned with
- * the start of a font line.
- */
- font_line_len = var->xres * var->bits_per_pixel * fontht / 8;
- min_size = var->xres * var->yres * var->bits_per_pixel / 8;
-
- /*
- * If minimum screen size is greater than that we have
- * available, reject it.
- */
- if (min_size > info->fix.smem_len)
- return -EINVAL;
-
- /* Find int 'y', such that y * fll == s * sam < maxsize
- * y = s * sam / fll; s = maxsize / sam
- */
- for (size = info->fix.smem_len;
- nr_y = size / font_line_len, min_size <= size;
- size -= sam_size) {
- if (nr_y * font_line_len == size)
- break;
- }
- nr_y *= fontht;
-
- if (var->accel_flags & FB_ACCELF_TEXT) {
- if (min_size > size) {
- /*
- * failed, use ypan
- */
- size = info->fix.smem_len;
- var->yres_virtual = size / (font_line_len / fontht);
- } else
- var->yres_virtual = nr_y;
- } else if (var->yres_virtual > nr_y)
- var->yres_virtual = nr_y;
-
- current_par.screen_end = info->fix.smem_start + size;
-
- /*
- * Fix yres & yoffset if needed.
- */
- if (var->yres > var->yres_virtual)
- var->yres = var->yres_virtual;
-
- if (var->vmode & FB_VMODE_YWRAP) {
- if (var->yoffset > var->yres_virtual)
- var->yoffset = var->yres_virtual;
- } else {
- if (var->yoffset + var->yres > var->yres_virtual)
- var->yoffset = var->yres_virtual - var->yres;
- }
-
- /* hsync_len must be even */
- var->hsync_len = (var->hsync_len + 1) & ~1;
-
-#if defined(HAS_VIDC20)
- /* left_margin must be even */
- if (var->left_margin & 1) {
- var->left_margin += 1;
- var->right_margin -= 1;
- }
-
- /* right_margin must be even */
- if (var->right_margin & 1)
- var->right_margin += 1;
-#endif
-
- if (var->vsync_len < 1)
- var->vsync_len = 1;
-
- return 0;
-}
-
-static int
-acornfb_validate_timing(struct fb_var_screeninfo *var,
- struct fb_monspecs *monspecs)
-{
- unsigned long hs, vs;
-
- /*
- * hs(Hz) = 10^12 / (pixclock * xtotal)
- * vs(Hz) = hs(Hz) / ytotal
- *
- * No need to do long long divisions or anything
- * like that if you factor it correctly
- */
- hs = 1953125000 / var->pixclock;
- hs = hs * 512 /
- (var->xres + var->left_margin + var->right_margin + var->hsync_len);
- vs = hs /
- (var->yres + var->upper_margin + var->lower_margin + var->vsync_len);
-
- return (vs >= monspecs->vfmin && vs <= monspecs->vfmax &&
- hs >= monspecs->hfmin && hs <= monspecs->hfmax) ? 0 : -EINVAL;
-}
-
-static inline void
-acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var)
-{
- u_int off = var->yoffset * info->fix.line_length;
-
-#if defined(HAS_MEMC)
- memc_write(VDMA_INIT, off >> 2);
-#elif defined(HAS_IOMD)
- iomd_writel(info->fix.smem_start + off, IOMD_VIDINIT);
-#endif
-}
-
-static int
-acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- u_int fontht;
- int err;
-
- /*
- * FIXME: Find the font height
- */
- fontht = 8;
-
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
- var->transp.msb_right = 0;
-
- switch (var->bits_per_pixel) {
- case 1: case 2: case 4: case 8:
- var->red.offset = 0;
- var->red.length = var->bits_per_pixel;
- var->green = var->red;
- var->blue = var->red;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
-
-#ifdef HAS_VIDC20
- case 16:
- var->red.offset = 0;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 5;
- var->blue.offset = 10;
- var->blue.length = 5;
- var->transp.offset = 15;
- var->transp.length = 1;
- break;
-
- case 32:
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 16;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 4;
- break;
-#endif
- default:
- return -EINVAL;
- }
-
- /*
- * Check to see if the pixel rate is valid.
- */
- if (!acornfb_valid_pixrate(var))
- return -EINVAL;
-
- /*
- * Validate and adjust the resolution to
- * match the video generator hardware.
- */
- err = acornfb_adjust_timing(info, var, fontht);
- if (err)
- return err;
-
- /*
- * Validate the timing against the
- * monitor hardware.
- */
- return acornfb_validate_timing(var, &info->monspecs);
-}
-
-static int acornfb_set_par(struct fb_info *info)
-{
- switch (info->var.bits_per_pixel) {
- case 1:
- current_par.palette_size = 2;
- info->fix.visual = FB_VISUAL_MONO10;
- break;
- case 2:
- current_par.palette_size = 4;
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- break;
- case 4:
- current_par.palette_size = 16;
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- break;
- case 8:
- current_par.palette_size = VIDC_PALETTE_SIZE;
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- break;
-#ifdef HAS_VIDC20
- case 16:
- current_par.palette_size = 32;
- info->fix.visual = FB_VISUAL_DIRECTCOLOR;
- break;
- case 32:
- current_par.palette_size = VIDC_PALETTE_SIZE;
- info->fix.visual = FB_VISUAL_DIRECTCOLOR;
- break;
-#endif
- default:
- BUG();
- }
-
- info->fix.line_length = (info->var.xres * info->var.bits_per_pixel) / 8;
-
-#if defined(HAS_MEMC)
- {
- unsigned long size = info->fix.smem_len - VDMA_XFERSIZE;
-
- memc_write(VDMA_START, 0);
- memc_write(VDMA_END, size >> 2);
- }
-#elif defined(HAS_IOMD)
- {
- unsigned long start, size;
- u_int control;
-
- start = info->fix.smem_start;
- size = current_par.screen_end;
-
- if (current_par.using_vram) {
- size -= current_par.vram_half_sam;
- control = DMA_CR_E | (current_par.vram_half_sam / 256);
- } else {
- size -= 16;
- control = DMA_CR_E | DMA_CR_D | 16;
- }
-
- iomd_writel(start, IOMD_VIDSTART);
- iomd_writel(size, IOMD_VIDEND);
- iomd_writel(control, IOMD_VIDCR);
- }
-#endif
-
- acornfb_update_dma(info, &info->var);
- acornfb_set_timing(info);
-
- return 0;
-}
-
-static int
-acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- u_int y_bottom = var->yoffset;
-
- if (!(var->vmode & FB_VMODE_YWRAP))
- y_bottom += info->var.yres;
-
- if (y_bottom > info->var.yres_virtual)
- return -EINVAL;
-
- acornfb_update_dma(info, var);
-
- return 0;
-}
-
-static const struct fb_ops acornfb_ops = {
- .owner = THIS_MODULE,
- FB_DEFAULT_IOMEM_OPS,
- .fb_check_var = acornfb_check_var,
- .fb_set_par = acornfb_set_par,
- .fb_setcolreg = acornfb_setcolreg,
- .fb_pan_display = acornfb_pan_display,
-};
-
-/*
- * Everything after here is initialisation!!!
- */
-static struct fb_videomode modedb[] = {
- { /* 320x256 @ 50Hz */
- NULL, 50, 320, 256, 125000, 92, 62, 35, 19, 38, 2,
- FB_SYNC_COMP_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }, { /* 640x250 @ 50Hz, 15.6 kHz hsync */
- NULL, 50, 640, 250, 62500, 185, 123, 38, 21, 76, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 640x256 @ 50Hz, 15.6 kHz hsync */
- NULL, 50, 640, 256, 62500, 185, 123, 35, 18, 76, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 640x512 @ 50Hz, 26.8 kHz hsync */
- NULL, 50, 640, 512, 41667, 113, 87, 18, 1, 56, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 640x250 @ 70Hz, 31.5 kHz hsync */
- NULL, 70, 640, 250, 39722, 48, 16, 109, 88, 96, 2,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 640x256 @ 70Hz, 31.5 kHz hsync */
- NULL, 70, 640, 256, 39722, 48, 16, 106, 85, 96, 2,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 640x352 @ 70Hz, 31.5 kHz hsync */
- NULL, 70, 640, 352, 39722, 48, 16, 58, 37, 96, 2,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 640x480 @ 60Hz, 31.5 kHz hsync */
- NULL, 60, 640, 480, 39722, 48, 16, 32, 11, 96, 2,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 800x600 @ 56Hz, 35.2 kHz hsync */
- NULL, 56, 800, 600, 27778, 101, 23, 22, 1, 100, 2,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 896x352 @ 60Hz, 21.8 kHz hsync */
- NULL, 60, 896, 352, 41667, 59, 27, 9, 0, 118, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 1024x 768 @ 60Hz, 48.4 kHz hsync */
- NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
- 0,
- FB_VMODE_NONINTERLACED
- }, { /* 1280x1024 @ 60Hz, 63.8 kHz hsync */
- NULL, 60, 1280, 1024, 9090, 186, 96, 38, 1, 160, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }
-};
-
-static struct fb_videomode acornfb_default_mode = {
- .name = NULL,
- .refresh = 60,
- .xres = 640,
- .yres = 480,
- .pixclock = 39722,
- .left_margin = 56,
- .right_margin = 16,
- .upper_margin = 34,
- .lower_margin = 9,
- .hsync_len = 88,
- .vsync_len = 2,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-static void acornfb_init_fbinfo(void)
-{
- static int first = 1;
-
- if (!first)
- return;
- first = 0;
-
- fb_info.fbops = &acornfb_ops;
- fb_info.flags = FBINFO_HWACCEL_YPAN;
- fb_info.pseudo_palette = current_par.pseudo_palette;
-
- strcpy(fb_info.fix.id, "Acorn");
- fb_info.fix.type = FB_TYPE_PACKED_PIXELS;
- fb_info.fix.type_aux = 0;
- fb_info.fix.xpanstep = 0;
- fb_info.fix.ypanstep = 1;
- fb_info.fix.ywrapstep = 1;
- fb_info.fix.line_length = 0;
- fb_info.fix.accel = FB_ACCEL_NONE;
-
- /*
- * setup initial parameters
- */
- memset(&fb_info.var, 0, sizeof(fb_info.var));
-
-#if defined(HAS_VIDC20)
- fb_info.var.red.length = 8;
- fb_info.var.transp.length = 4;
-#endif
- fb_info.var.green = fb_info.var.red;
- fb_info.var.blue = fb_info.var.red;
- fb_info.var.nonstd = 0;
- fb_info.var.activate = FB_ACTIVATE_NOW;
- fb_info.var.height = -1;
- fb_info.var.width = -1;
- fb_info.var.vmode = FB_VMODE_NONINTERLACED;
- fb_info.var.accel_flags = FB_ACCELF_TEXT;
-
- current_par.dram_size = 0;
- current_par.montype = -1;
- current_par.dpms = 0;
-}
-
-/*
- * setup acornfb options:
- *
- * mon:hmin-hmax:vmin-vmax:dpms:width:height
- * Set monitor parameters:
- * hmin = horizontal minimum frequency (Hz)
- * hmax = horizontal maximum frequency (Hz) (optional)
- * vmin = vertical minimum frequency (Hz)
- * vmax = vertical maximum frequency (Hz) (optional)
- * dpms = DPMS supported? (optional)
- * width = width of picture in mm. (optional)
- * height = height of picture in mm. (optional)
- *
- * montype:type
- * Set RISC-OS style monitor type:
- * 0 (or tv) - TV frequency
- * 1 (or multi) - Multi frequency
- * 2 (or hires) - Hi-res monochrome
- * 3 (or vga) - VGA
- * 4 (or svga) - SVGA
- * auto, or option missing
- * - try hardware detect
- *
- * dram:size
- * Set the amount of DRAM to use for the frame buffer
- * (even if you have VRAM).
- * size can optionally be followed by 'M' or 'K' for
- * MB or KB respectively.
- */
-static void acornfb_parse_mon(char *opt)
-{
- char *p = opt;
-
- current_par.montype = -2;
-
- fb_info.monspecs.hfmin = simple_strtoul(p, &p, 0);
- if (*p == '-')
- fb_info.monspecs.hfmax = simple_strtoul(p + 1, &p, 0);
- else
- fb_info.monspecs.hfmax = fb_info.monspecs.hfmin;
-
- if (*p != ':')
- goto bad;
-
- fb_info.monspecs.vfmin = simple_strtoul(p + 1, &p, 0);
- if (*p == '-')
- fb_info.monspecs.vfmax = simple_strtoul(p + 1, &p, 0);
- else
- fb_info.monspecs.vfmax = fb_info.monspecs.vfmin;
-
- if (*p != ':')
- goto check_values;
-
- fb_info.monspecs.dpms = simple_strtoul(p + 1, &p, 0);
-
- if (*p != ':')
- goto check_values;
-
- fb_info.var.width = simple_strtoul(p + 1, &p, 0);
-
- if (*p != ':')
- goto check_values;
-
- fb_info.var.height = simple_strtoul(p + 1, NULL, 0);
-
-check_values:
- if (fb_info.monspecs.hfmax < fb_info.monspecs.hfmin ||
- fb_info.monspecs.vfmax < fb_info.monspecs.vfmin)
- goto bad;
- return;
-
-bad:
- printk(KERN_ERR "Acornfb: bad monitor settings: %s\n", opt);
- current_par.montype = -1;
-}
-
-static void acornfb_parse_montype(char *opt)
-{
- current_par.montype = -2;
-
- if (strncmp(opt, "tv", 2) == 0) {
- opt += 2;
- current_par.montype = 0;
- } else if (strncmp(opt, "multi", 5) == 0) {
- opt += 5;
- current_par.montype = 1;
- } else if (strncmp(opt, "hires", 5) == 0) {
- opt += 5;
- current_par.montype = 2;
- } else if (strncmp(opt, "vga", 3) == 0) {
- opt += 3;
- current_par.montype = 3;
- } else if (strncmp(opt, "svga", 4) == 0) {
- opt += 4;
- current_par.montype = 4;
- } else if (strncmp(opt, "auto", 4) == 0) {
- opt += 4;
- current_par.montype = -1;
- } else if (isdigit(*opt))
- current_par.montype = simple_strtoul(opt, &opt, 0);
-
- if (current_par.montype == -2 ||
- current_par.montype > NR_MONTYPES) {
- printk(KERN_ERR "acornfb: unknown monitor type: %s\n",
- opt);
- current_par.montype = -1;
- } else
- if (opt && *opt) {
- if (strcmp(opt, ",dpms") == 0)
- current_par.dpms = 1;
- else
- printk(KERN_ERR
- "acornfb: unknown monitor option: %s\n",
- opt);
- }
-}
-
-static void acornfb_parse_dram(char *opt)
-{
- unsigned int size;
-
- size = simple_strtoul(opt, &opt, 0);
-
- if (opt) {
- switch (*opt) {
- case 'M':
- case 'm':
- size *= 1024;
- fallthrough;
- case 'K':
- case 'k':
- size *= 1024;
- default:
- break;
- }
- }
-
- current_par.dram_size = size;
-}
-
-static struct options {
- char *name;
- void (*parse)(char *opt);
-} opt_table[] = {
- { "mon", acornfb_parse_mon },
- { "montype", acornfb_parse_montype },
- { "dram", acornfb_parse_dram },
- { NULL, NULL }
-};
-
-static int acornfb_setup(char *options)
-{
- struct options *optp;
- char *opt;
-
- if (!options || !*options)
- return 0;
-
- acornfb_init_fbinfo();
-
- while ((opt = strsep(&options, ",")) != NULL) {
- if (!*opt)
- continue;
-
- for (optp = opt_table; optp->name; optp++) {
- int optlen;
-
- optlen = strlen(optp->name);
-
- if (strncmp(opt, optp->name, optlen) == 0 &&
- opt[optlen] == ':') {
- optp->parse(opt + optlen + 1);
- break;
- }
- }
-
- if (!optp->name)
- printk(KERN_ERR "acornfb: unknown parameter: %s\n",
- opt);
- }
- return 0;
-}
-
-/*
- * Detect type of monitor connected
- * For now, we just assume SVGA
- */
-static int acornfb_detect_monitortype(void)
-{
- return 4;
-}
-
-static int acornfb_probe(struct platform_device *dev)
-{
- unsigned long size;
- u_int h_sync, v_sync;
- int rc, i;
- char *option = NULL;
-
- if (fb_get_options("acornfb", &option))
- return -ENODEV;
- acornfb_setup(option);
-
- acornfb_init_fbinfo();
-
- current_par.dev = &dev->dev;
-
- if (current_par.montype == -1)
- current_par.montype = acornfb_detect_monitortype();
-
- if (current_par.montype == -1 || current_par.montype > NR_MONTYPES)
- current_par.montype = 4;
-
- if (current_par.montype >= 0) {
- fb_info.monspecs = monspecs[current_par.montype];
- fb_info.monspecs.dpms = current_par.dpms;
- }
-
- /*
- * Try to select a suitable default mode
- */
- for (i = 0; i < ARRAY_SIZE(modedb); i++) {
- unsigned long hs;
-
- hs = modedb[i].refresh *
- (modedb[i].yres + modedb[i].upper_margin +
- modedb[i].lower_margin + modedb[i].vsync_len);
- if (modedb[i].xres == DEFAULT_XRES &&
- modedb[i].yres == DEFAULT_YRES &&
- modedb[i].refresh >= fb_info.monspecs.vfmin &&
- modedb[i].refresh <= fb_info.monspecs.vfmax &&
- hs >= fb_info.monspecs.hfmin &&
- hs <= fb_info.monspecs.hfmax) {
- acornfb_default_mode = modedb[i];
- break;
- }
- }
-
- fb_info.screen_base = (char *)SCREEN_BASE;
- fb_info.fix.smem_start = SCREEN_START;
- current_par.using_vram = 0;
-
- /*
- * If vram_size is set, we are using VRAM in
- * a Risc PC. However, if the user has specified
- * an amount of DRAM then use that instead.
- */
- if (vram_size && !current_par.dram_size) {
- size = vram_size;
- current_par.vram_half_sam = vram_size / 1024;
- current_par.using_vram = 1;
- } else if (current_par.dram_size)
- size = current_par.dram_size;
- else
- size = MAX_SIZE;
-
- /*
- * Limit maximum screen size.
- */
- if (size > MAX_SIZE)
- size = MAX_SIZE;
-
- size = PAGE_ALIGN(size);
-
-#if defined(HAS_VIDC20)
- if (!current_par.using_vram) {
- dma_addr_t handle;
- void *base;
-
- /*
- * RiscPC needs to allocate the DRAM memory
- * for the framebuffer if we are not using
- * VRAM.
- */
- base = dma_alloc_wc(current_par.dev, size, &handle,
- GFP_KERNEL);
- if (base == NULL) {
- printk(KERN_ERR "acornfb: unable to allocate screen memory\n");
- return -ENOMEM;
- }
-
- fb_info.screen_base = base;
- fb_info.fix.smem_start = handle;
- }
-#endif
- fb_info.fix.smem_len = size;
- current_par.palette_size = VIDC_PALETTE_SIZE;
-
- /*
- * Lookup the timing for this resolution. If we can't
- * find it, then we can't restore it if we change
- * the resolution, so we disable this feature.
- */
- do {
- rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
- ARRAY_SIZE(modedb),
- &acornfb_default_mode, DEFAULT_BPP);
- /*
- * If we found an exact match, all ok.
- */
- if (rc == 1)
- break;
-
- rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
- &acornfb_default_mode, DEFAULT_BPP);
- /*
- * If we found an exact match, all ok.
- */
- if (rc == 1)
- break;
-
- rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
- ARRAY_SIZE(modedb),
- &acornfb_default_mode, DEFAULT_BPP);
- if (rc)
- break;
-
- rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
- &acornfb_default_mode, DEFAULT_BPP);
- } while (0);
-
- /*
- * If we didn't find an exact match, try the
- * generic database.
- */
- if (rc == 0) {
- printk("Acornfb: no valid mode found\n");
- return -EINVAL;
- }
-
- h_sync = 1953125000 / fb_info.var.pixclock;
- h_sync = h_sync * 512 / (fb_info.var.xres + fb_info.var.left_margin +
- fb_info.var.right_margin + fb_info.var.hsync_len);
- v_sync = h_sync / (fb_info.var.yres + fb_info.var.upper_margin +
- fb_info.var.lower_margin + fb_info.var.vsync_len);
-
- printk(KERN_INFO "Acornfb: %dkB %cRAM, %s, using %dx%d, %d.%03dkHz, %dHz\n",
- fb_info.fix.smem_len / 1024,
- current_par.using_vram ? 'V' : 'D',
- VIDC_NAME, fb_info.var.xres, fb_info.var.yres,
- h_sync / 1000, h_sync % 1000, v_sync);
-
- printk(KERN_INFO "Acornfb: Monitor: %d.%03d-%d.%03dkHz, %d-%dHz%s\n",
- fb_info.monspecs.hfmin / 1000, fb_info.monspecs.hfmin % 1000,
- fb_info.monspecs.hfmax / 1000, fb_info.monspecs.hfmax % 1000,
- fb_info.monspecs.vfmin, fb_info.monspecs.vfmax,
- fb_info.monspecs.dpms ? ", DPMS" : "");
-
- if (fb_set_var(&fb_info, &fb_info.var))
- printk(KERN_ERR "Acornfb: unable to set display parameters\n");
-
- if (register_framebuffer(&fb_info) < 0)
- return -EINVAL;
- return 0;
-}
-
-static struct platform_driver acornfb_driver = {
- .probe = acornfb_probe,
- .driver = {
- .name = "acornfb",
- },
-};
-
-static int __init acornfb_init(void)
-{
- return platform_driver_register(&acornfb_driver);
-}
-
-module_init(acornfb_init);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/acornfb.h b/drivers/video/fbdev/acornfb.h
deleted file mode 100644
index f8df4ecb4..000000000
--- a/drivers/video/fbdev/acornfb.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * linux/drivers/video/acornfb.h
- *
- * Copyright (C) 1998,1999 Russell King
- *
- * Frame buffer code for Acorn platforms
- */
-#if defined(HAS_VIDC20)
-#include <asm/hardware/iomd.h>
-#define VIDC_PALETTE_SIZE 256
-#define VIDC_NAME "VIDC20"
-#endif
-
-#define EXTEND8(x) ((x)|(x)<<8)
-#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
-
-struct vidc20_palette {
- u_int red:8;
- u_int green:8;
- u_int blue:8;
- u_int ext:4;
- u_int unused:4;
-};
-
-struct vidc_palette {
- u_int red:4;
- u_int green:4;
- u_int blue:4;
- u_int trans:1;
- u_int sbz1:13;
- u_int reg:4;
- u_int sbz2:2;
-};
-
-union palette {
- struct vidc20_palette vidc20;
- struct vidc_palette vidc;
- u_int p;
-};
-
-struct acornfb_par {
- struct device *dev;
- unsigned long screen_end;
- unsigned int dram_size;
- unsigned int vram_half_sam;
- unsigned int palette_size;
- signed int montype;
- unsigned int using_vram : 1;
- unsigned int dpms : 1;
-
- union palette palette[VIDC_PALETTE_SIZE];
-
- u32 pseudo_palette[16];
-};
-
-struct vidc_timing {
- u_int h_cycle;
- u_int h_sync_width;
- u_int h_border_start;
- u_int h_display_start;
- u_int h_display_end;
- u_int h_border_end;
- u_int h_interlace;
-
- u_int v_cycle;
- u_int v_sync_width;
- u_int v_border_start;
- u_int v_display_start;
- u_int v_display_end;
- u_int v_border_end;
-
- u_int control;
-
- /* VIDC20 only */
- u_int pll_ctl;
-};
-
-struct modey_params {
- u_int y_res;
- u_int u_margin;
- u_int b_margin;
- u_int vsync_len;
- u_int vf;
-};
-
-struct modex_params {
- u_int x_res;
- u_int l_margin;
- u_int r_margin;
- u_int hsync_len;
- u_int clock;
- u_int hf;
- const struct modey_params *modey;
-};
-
-#ifdef HAS_VIDC20
-/*
- * VIDC20 registers
- */
-#define VIDC20_CTRL 0xe0000000
-#define VIDC20_CTRL_PIX_VCLK (0 << 0)
-#define VIDC20_CTRL_PIX_HCLK (1 << 0)
-#define VIDC20_CTRL_PIX_RCLK (2 << 0)
-#define VIDC20_CTRL_PIX_CK (0 << 2)
-#define VIDC20_CTRL_PIX_CK2 (1 << 2)
-#define VIDC20_CTRL_PIX_CK3 (2 << 2)
-#define VIDC20_CTRL_PIX_CK4 (3 << 2)
-#define VIDC20_CTRL_PIX_CK5 (4 << 2)
-#define VIDC20_CTRL_PIX_CK6 (5 << 2)
-#define VIDC20_CTRL_PIX_CK7 (6 << 2)
-#define VIDC20_CTRL_PIX_CK8 (7 << 2)
-#define VIDC20_CTRL_1BPP (0 << 5)
-#define VIDC20_CTRL_2BPP (1 << 5)
-#define VIDC20_CTRL_4BPP (2 << 5)
-#define VIDC20_CTRL_8BPP (3 << 5)
-#define VIDC20_CTRL_16BPP (4 << 5)
-#define VIDC20_CTRL_32BPP (6 << 5)
-#define VIDC20_CTRL_FIFO_NS (0 << 8)
-#define VIDC20_CTRL_FIFO_4 (1 << 8)
-#define VIDC20_CTRL_FIFO_8 (2 << 8)
-#define VIDC20_CTRL_FIFO_12 (3 << 8)
-#define VIDC20_CTRL_FIFO_16 (4 << 8)
-#define VIDC20_CTRL_FIFO_20 (5 << 8)
-#define VIDC20_CTRL_FIFO_24 (6 << 8)
-#define VIDC20_CTRL_FIFO_28 (7 << 8)
-#define VIDC20_CTRL_INT (1 << 12)
-#define VIDC20_CTRL_DUP (1 << 13)
-#define VIDC20_CTRL_PDOWN (1 << 14)
-
-#define VIDC20_ECTL 0xc0000000
-#define VIDC20_ECTL_REG(x) ((x) & 0xf3)
-#define VIDC20_ECTL_ECK (1 << 2)
-#define VIDC20_ECTL_REDPED (1 << 8)
-#define VIDC20_ECTL_GREENPED (1 << 9)
-#define VIDC20_ECTL_BLUEPED (1 << 10)
-#define VIDC20_ECTL_DAC (1 << 12)
-#define VIDC20_ECTL_LCDGS (1 << 13)
-#define VIDC20_ECTL_HRM (1 << 14)
-
-#define VIDC20_ECTL_HS_MASK (3 << 16)
-#define VIDC20_ECTL_HS_HSYNC (0 << 16)
-#define VIDC20_ECTL_HS_NHSYNC (1 << 16)
-#define VIDC20_ECTL_HS_CSYNC (2 << 16)
-#define VIDC20_ECTL_HS_NCSYNC (3 << 16)
-
-#define VIDC20_ECTL_VS_MASK (3 << 18)
-#define VIDC20_ECTL_VS_VSYNC (0 << 18)
-#define VIDC20_ECTL_VS_NVSYNC (1 << 18)
-#define VIDC20_ECTL_VS_CSYNC (2 << 18)
-#define VIDC20_ECTL_VS_NCSYNC (3 << 18)
-
-#define VIDC20_DCTL 0xf0000000
-/* 0-9 = number of words in scanline */
-#define VIDC20_DCTL_SNA (1 << 12)
-#define VIDC20_DCTL_HDIS (1 << 13)
-#define VIDC20_DCTL_BUS_NS (0 << 16)
-#define VIDC20_DCTL_BUS_D31_0 (1 << 16)
-#define VIDC20_DCTL_BUS_D63_32 (2 << 16)
-#define VIDC20_DCTL_BUS_D63_0 (3 << 16)
-#define VIDC20_DCTL_VRAM_DIS (0 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK (1 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK2 (2 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK4 (3 << 18)
-
-#endif
diff --git a/drivers/video/fbdev/amifb.c b/drivers/video/fbdev/amifb.c
deleted file mode 100644
index 1116a0789..000000000
--- a/drivers/video/fbdev/amifb.c
+++ /dev/null
@@ -1,3787 +0,0 @@
-/*
- * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device
- *
- * Copyright (C) 1995-2003 Geert Uytterhoeven
- *
- * with work by Roman Zippel
- *
- *
- * This file is based on the Atari frame buffer device (atafb.c):
- *
- * Copyright (C) 1994 Martin Schaller
- * Roman Hodek
- *
- * with work by Andreas Schwab
- * Guenther Kelleter
- *
- * and on the original Amiga console driver (amicon.c):
- *
- * Copyright (C) 1993 Hamish Macdonald
- * Greg Harp
- * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
- *
- * with work by William Rucklidge (wjr@cs.cornell.edu)
- * Geert Uytterhoeven
- * Jes Sorensen (jds@kom.auc.dk)
- *
- *
- * History:
- *
- * - 24 Jul 96: Copper generates now vblank interrupt and
- * VESA Power Saving Protocol is fully implemented
- * - 14 Jul 96: Rework and hopefully last ECS bugs fixed
- * - 7 Mar 96: Hardware sprite support by Roman Zippel
- * - 18 Feb 96: OCS and ECS support by Roman Zippel
- * Hardware functions completely rewritten
- * - 2 Dec 95: AGA version by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-
-#include <asm/irq.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/setup.h>
-
-#include "c2p.h"
-
-
-#define DEBUG
-
-#if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
-#define CONFIG_FB_AMIGA_OCS /* define at least one fb driver, this will change later */
-#endif
-
-#if !defined(CONFIG_FB_AMIGA_OCS)
-# define IS_OCS (0)
-#elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
-# define IS_OCS (chipset == TAG_OCS)
-#else
-# define CONFIG_FB_AMIGA_OCS_ONLY
-# define IS_OCS (1)
-#endif
-
-#if !defined(CONFIG_FB_AMIGA_ECS)
-# define IS_ECS (0)
-#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
-# define IS_ECS (chipset == TAG_ECS)
-#else
-# define CONFIG_FB_AMIGA_ECS_ONLY
-# define IS_ECS (1)
-#endif
-
-#if !defined(CONFIG_FB_AMIGA_AGA)
-# define IS_AGA (0)
-#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
-# define IS_AGA (chipset == TAG_AGA)
-#else
-# define CONFIG_FB_AMIGA_AGA_ONLY
-# define IS_AGA (1)
-#endif
-
-#ifdef DEBUG
-# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
-#else
-# define DPRINTK(fmt, args...)
-#endif
-
-/*******************************************************************************
-
-
- Generic video timings
- ---------------------
-
- Timings used by the frame buffer interface:
-
- +----------+---------------------------------------------+----------+-------+
- | | ^ | | |
- | | |upper_margin | | |
- | | v | | |
- +----------###############################################----------+-------+
- | # ^ # | |
- | # | # | |
- | # | # | |
- | # | # | |
- | left # | # right | hsync |
- | margin # | xres # margin | len |
- |<-------->#<---------------+--------------------------->#<-------->|<----->|
- | # | # | |
- | # | # | |
- | # | # | |
- | # |yres # | |
- | # | # | |
- | # | # | |
- | # | # | |
- | # | # | |
- | # | # | |
- | # | # | |
- | # | # | |
- | # | # | |
- | # v # | |
- +----------###############################################----------+-------+
- | | ^ | | |
- | | |lower_margin | | |
- | | v | | |
- +----------+---------------------------------------------+----------+-------+
- | | ^ | | |
- | | |vsync_len | | |
- | | v | | |
- +----------+---------------------------------------------+----------+-------+
-
-
- Amiga video timings
- -------------------
-
- The Amiga native chipsets uses another timing scheme:
-
- - hsstrt: Start of horizontal synchronization pulse
- - hsstop: End of horizontal synchronization pulse
- - htotal: Last value on the line (i.e. line length = htotal + 1)
- - vsstrt: Start of vertical synchronization pulse
- - vsstop: End of vertical synchronization pulse
- - vtotal: Last line value (i.e. number of lines = vtotal + 1)
- - hcenter: Start of vertical retrace for interlace
-
- You can specify the blanking timings independently. Currently I just set
- them equal to the respective synchronization values:
-
- - hbstrt: Start of horizontal blank
- - hbstop: End of horizontal blank
- - vbstrt: Start of vertical blank
- - vbstop: End of vertical blank
-
- Horizontal values are in color clock cycles (280 ns), vertical values are in
- scanlines.
-
- (0, 0) is somewhere in the upper-left corner :-)
-
-
- Amiga visible window definitions
- --------------------------------
-
- Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to
- make corrections and/or additions.
-
- Within the above synchronization specifications, the visible window is
- defined by the following parameters (actual register resolutions may be
- different; all horizontal values are normalized with respect to the pixel
- clock):
-
- - diwstrt_h: Horizontal start of the visible window
- - diwstop_h: Horizontal stop + 1(*) of the visible window
- - diwstrt_v: Vertical start of the visible window
- - diwstop_v: Vertical stop of the visible window
- - ddfstrt: Horizontal start of display DMA
- - ddfstop: Horizontal stop of display DMA
- - hscroll: Horizontal display output delay
-
- Sprite positioning:
-
- - sprstrt_h: Horizontal start - 4 of sprite
- - sprstrt_v: Vertical start of sprite
-
- (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
-
- Horizontal values are in dotclock cycles (35 ns), vertical values are in
- scanlines.
-
- (0, 0) is somewhere in the upper-left corner :-)
-
-
- Dependencies (AGA, SHRES (35 ns dotclock))
- -------------------------------------------
-
- Since there are much more parameters for the Amiga display than for the
- frame buffer interface, there must be some dependencies among the Amiga
- display parameters. Here's what I found out:
-
- - ddfstrt and ddfstop are best aligned to 64 pixels.
- - the chipset needs 64 + 4 horizontal pixels after the DMA start before
- the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
- to display the first pixel on the line too. Increase diwstrt_h for
- virtual screen panning.
- - the display DMA always fetches 64 pixels at a time (fmode = 3).
- - ddfstop is ddfstrt+#pixels - 64.
- - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
- be 1 more than htotal.
- - hscroll simply adds a delay to the display output. Smooth horizontal
- panning needs an extra 64 pixels on the left to prefetch the pixels that
- `fall off' on the left.
- - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
- DMA, so it's best to make the DMA start as late as possible.
- - you really don't want to make ddfstrt < 128, since this will steal DMA
- cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
- - I make diwstop_h and diwstop_v as large as possible.
-
- General dependencies
- --------------------
-
- - all values are SHRES pixel (35ns)
-
- table 1:fetchstart table 2:prefetch table 3:fetchsize
- ------------------ ---------------- -----------------
- Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
- -------------#------+-----+------#------+-----+------#------+-----+------
- Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64
- Bus width 2x # 32 | 64 | 128 # 32 | 64 | 64 # 64 | 64 | 128
- Bus width 4x # 64 | 128 | 256 # 64 | 64 | 64 # 64 | 128 | 256
-
- - chipset needs 4 pixels before the first pixel is output
- - ddfstrt must be aligned to fetchstart (table 1)
- - chipset needs also prefetch (table 2) to get first pixel data, so
- ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
- - for horizontal panning decrease diwstrt_h
- - the length of a fetchline must be aligned to fetchsize (table 3)
- - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
- moved to optimize use of dma (useful for OCS/ECS overscan displays)
- - ddfstop is ddfstrt + ddfsize - fetchsize
- - If C= didn't change anything for AGA, then at following positions the
- dma bus is already used:
- ddfstrt < 48 -> memory refresh
- < 96 -> disk dma
- < 160 -> audio dma
- < 192 -> sprite 0 dma
- < 416 -> sprite dma (32 per sprite)
- - in accordance with the hardware reference manual a hardware stop is at
- 192, but AGA (ECS?) can go below this.
-
- DMA priorities
- --------------
-
- Since there are limits on the earliest start value for display DMA and the
- display of sprites, I use the following policy on horizontal panning and
- the hardware cursor:
-
- - if you want to start display DMA too early, you lose the ability to
- do smooth horizontal panning (xpanstep 1 -> 64).
- - if you want to go even further, you lose the hardware cursor too.
-
- IMHO a hardware cursor is more important for X than horizontal scrolling,
- so that's my motivation.
-
-
- Implementation
- --------------
-
- ami_decode_var() converts the frame buffer values to the Amiga values. It's
- just a `straightforward' implementation of the above rules.
-
-
- Standard VGA timings
- --------------------
-
- xres yres left right upper lower hsync vsync
- ---- ---- ---- ----- ----- ----- ----- -----
- 80x25 720 400 27 45 35 12 108 2
- 80x30 720 480 27 45 30 9 108 2
-
- These were taken from a XFree86 configuration file, recalculated for a 28 MHz
- dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer
- generic timings.
-
- As a comparison, graphics/monitor.h suggests the following:
-
- xres yres left right upper lower hsync vsync
- ---- ---- ---- ----- ----- ----- ----- -----
-
- VGA 640 480 52 112 24 19 112 - 2 +
- VGA70 640 400 52 112 27 21 112 - 2 -
-
-
- Sync polarities
- ---------------
-
- VSYNC HSYNC Vertical size Vertical total
- ----- ----- ------------- --------------
- + + Reserved Reserved
- + - 400 414
- - + 350 362
- - - 480 496
-
- Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
-
-
- Broadcast video timings
- -----------------------
-
- According to the CCIR and RETMA specifications, we have the following values:
-
- CCIR -> PAL
- -----------
-
- - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
- 736 visible 70 ns pixels per line.
- - we have 625 scanlines, of which 575 are visible (interlaced); after
- rounding this becomes 576.
-
- RETMA -> NTSC
- -------------
-
- - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about
- 736 visible 70 ns pixels per line.
- - we have 525 scanlines, of which 485 are visible (interlaced); after
- rounding this becomes 484.
-
- Thus if you want a PAL compatible display, you have to do the following:
-
- - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
- timings are to be used.
- - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
- interlaced, 312 for a non-interlaced and 156 for a doublescanned
- display.
- - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
- SHRES, 908 for a HIRES and 454 for a LORES display.
- - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
- left_margin + 2 * hsync_len must be greater or equal.
- - the upper visible part begins at 48 (interlaced; non-interlaced:24,
- doublescanned:12), upper_margin + 2 * vsync_len must be greater or
- equal.
- - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
- of 4 scanlines
-
- The settings for a NTSC compatible display are straightforward.
-
- Note that in a strict sense the PAL and NTSC standards only define the
- encoding of the color part (chrominance) of the video signal and don't say
- anything about horizontal/vertical synchronization nor refresh rates.
-
-
- -- Geert --
-
-*******************************************************************************/
-
-
- /*
- * Custom Chipset Definitions
- */
-
-#define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
-
- /*
- * BPLCON0 -- Bitplane Control Register 0
- */
-
-#define BPC0_HIRES (0x8000)
-#define BPC0_BPU2 (0x4000) /* Bit plane used count */
-#define BPC0_BPU1 (0x2000)
-#define BPC0_BPU0 (0x1000)
-#define BPC0_HAM (0x0800) /* HAM mode */
-#define BPC0_DPF (0x0400) /* Double playfield */
-#define BPC0_COLOR (0x0200) /* Enable colorburst */
-#define BPC0_GAUD (0x0100) /* Genlock audio enable */
-#define BPC0_UHRES (0x0080) /* Ultrahi res enable */
-#define BPC0_SHRES (0x0040) /* Super hi res mode */
-#define BPC0_BYPASS (0x0020) /* Bypass LUT - AGA */
-#define BPC0_BPU3 (0x0010) /* AGA */
-#define BPC0_LPEN (0x0008) /* Light pen enable */
-#define BPC0_LACE (0x0004) /* Interlace */
-#define BPC0_ERSY (0x0002) /* External resync */
-#define BPC0_ECSENA (0x0001) /* ECS enable */
-
- /*
- * BPLCON2 -- Bitplane Control Register 2
- */
-
-#define BPC2_ZDBPSEL2 (0x4000) /* Bitplane to be used for ZD - AGA */
-#define BPC2_ZDBPSEL1 (0x2000)
-#define BPC2_ZDBPSEL0 (0x1000)
-#define BPC2_ZDBPEN (0x0800) /* Enable ZD with ZDBPSELx - AGA */
-#define BPC2_ZDCTEN (0x0400) /* Enable ZD with palette bit #31 - AGA */
-#define BPC2_KILLEHB (0x0200) /* Kill EHB mode - AGA */
-#define BPC2_RDRAM (0x0100) /* Color table accesses read, not write - AGA */
-#define BPC2_SOGEN (0x0080) /* SOG output pin high - AGA */
-#define BPC2_PF2PRI (0x0040) /* PF2 priority over PF1 */
-#define BPC2_PF2P2 (0x0020) /* PF2 priority wrt sprites */
-#define BPC2_PF2P1 (0x0010)
-#define BPC2_PF2P0 (0x0008)
-#define BPC2_PF1P2 (0x0004) /* ditto PF1 */
-#define BPC2_PF1P1 (0x0002)
-#define BPC2_PF1P0 (0x0001)
-
- /*
- * BPLCON3 -- Bitplane Control Register 3 (AGA)
- */
-
-#define BPC3_BANK2 (0x8000) /* Bits to select color register bank */
-#define BPC3_BANK1 (0x4000)
-#define BPC3_BANK0 (0x2000)
-#define BPC3_PF2OF2 (0x1000) /* Bits for color table offset when PF2 */
-#define BPC3_PF2OF1 (0x0800)
-#define BPC3_PF2OF0 (0x0400)
-#define BPC3_LOCT (0x0200) /* Color register writes go to low bits */
-#define BPC3_SPRES1 (0x0080) /* Sprite resolution bits */
-#define BPC3_SPRES0 (0x0040)
-#define BPC3_BRDRBLNK (0x0020) /* Border blanked? */
-#define BPC3_BRDRTRAN (0x0010) /* Border transparent? */
-#define BPC3_ZDCLKEN (0x0004) /* ZD pin is 14 MHz (HIRES) clock output */
-#define BPC3_BRDRSPRT (0x0002) /* Sprites in border? */
-#define BPC3_EXTBLKEN (0x0001) /* BLANK programmable */
-
- /*
- * BPLCON4 -- Bitplane Control Register 4 (AGA)
- */
-
-#define BPC4_BPLAM7 (0x8000) /* bitplane color XOR field */
-#define BPC4_BPLAM6 (0x4000)
-#define BPC4_BPLAM5 (0x2000)
-#define BPC4_BPLAM4 (0x1000)
-#define BPC4_BPLAM3 (0x0800)
-#define BPC4_BPLAM2 (0x0400)
-#define BPC4_BPLAM1 (0x0200)
-#define BPC4_BPLAM0 (0x0100)
-#define BPC4_ESPRM7 (0x0080) /* 4 high bits for even sprite colors */
-#define BPC4_ESPRM6 (0x0040)
-#define BPC4_ESPRM5 (0x0020)
-#define BPC4_ESPRM4 (0x0010)
-#define BPC4_OSPRM7 (0x0008) /* 4 high bits for odd sprite colors */
-#define BPC4_OSPRM6 (0x0004)
-#define BPC4_OSPRM5 (0x0002)
-#define BPC4_OSPRM4 (0x0001)
-
- /*
- * BEAMCON0 -- Beam Control Register
- */
-
-#define BMC0_HARDDIS (0x4000) /* Disable hardware limits */
-#define BMC0_LPENDIS (0x2000) /* Disable light pen latch */
-#define BMC0_VARVBEN (0x1000) /* Enable variable vertical blank */
-#define BMC0_LOLDIS (0x0800) /* Disable long/short line toggle */
-#define BMC0_CSCBEN (0x0400) /* Composite sync/blank */
-#define BMC0_VARVSYEN (0x0200) /* Enable variable vertical sync */
-#define BMC0_VARHSYEN (0x0100) /* Enable variable horizontal sync */
-#define BMC0_VARBEAMEN (0x0080) /* Enable variable beam counters */
-#define BMC0_DUAL (0x0040) /* Enable alternate horizontal beam counter */
-#define BMC0_PAL (0x0020) /* Set decodes for PAL */
-#define BMC0_VARCSYEN (0x0010) /* Enable variable composite sync */
-#define BMC0_BLANKEN (0x0008) /* Blank enable (no longer used on AGA) */
-#define BMC0_CSYTRUE (0x0004) /* CSY polarity */
-#define BMC0_VSYTRUE (0x0002) /* VSY polarity */
-#define BMC0_HSYTRUE (0x0001) /* HSY polarity */
-
-
- /*
- * FMODE -- Fetch Mode Control Register (AGA)
- */
-
-#define FMODE_SSCAN2 (0x8000) /* Sprite scan-doubling */
-#define FMODE_BSCAN2 (0x4000) /* Use PF2 modulus every other line */
-#define FMODE_SPAGEM (0x0008) /* Sprite page mode */
-#define FMODE_SPR32 (0x0004) /* Sprite 32 bit fetch */
-#define FMODE_BPAGEM (0x0002) /* Bitplane page mode */
-#define FMODE_BPL32 (0x0001) /* Bitplane 32 bit fetch */
-
- /*
- * Tags used to indicate a specific Pixel Clock
- *
- * clk_shift is the shift value to get the timings in 35 ns units
- */
-
-enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
-
- /*
- * Tags used to indicate the specific chipset
- */
-
-enum { TAG_OCS, TAG_ECS, TAG_AGA };
-
- /*
- * Tags used to indicate the memory bandwidth
- */
-
-enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
-
-
- /*
- * Clock Definitions, Maximum Display Depth
- *
- * These depend on the E-Clock or the Chipset, so they are filled in
- * dynamically
- */
-
-static u_long pixclock[3]; /* SHRES/HIRES/LORES: index = clk_shift */
-static u_short maxdepth[3]; /* SHRES/HIRES/LORES: index = clk_shift */
-static u_short maxfmode, chipset;
-
-
- /*
- * Broadcast Video Timings
- *
- * Horizontal values are in 35 ns (SHRES) units
- * Vertical values are in interlaced scanlines
- */
-
-#define PAL_DIWSTRT_H (360) /* PAL Window Limits */
-#define PAL_DIWSTRT_V (48)
-#define PAL_HTOTAL (1816)
-#define PAL_VTOTAL (625)
-
-#define NTSC_DIWSTRT_H (360) /* NTSC Window Limits */
-#define NTSC_DIWSTRT_V (40)
-#define NTSC_HTOTAL (1816)
-#define NTSC_VTOTAL (525)
-
-
- /*
- * Various macros
- */
-
-#define up2(v) (((v) + 1) & -2)
-#define down2(v) ((v) & -2)
-#define div2(v) ((v)>>1)
-#define mod2(v) ((v) & 1)
-
-#define up4(v) (((v) + 3) & -4)
-#define down4(v) ((v) & -4)
-#define mul4(v) ((v) << 2)
-#define div4(v) ((v)>>2)
-#define mod4(v) ((v) & 3)
-
-#define up8(v) (((v) + 7) & -8)
-#define down8(v) ((v) & -8)
-#define div8(v) ((v)>>3)
-#define mod8(v) ((v) & 7)
-
-#define up16(v) (((v) + 15) & -16)
-#define down16(v) ((v) & -16)
-#define div16(v) ((v)>>4)
-#define mod16(v) ((v) & 15)
-
-#define up32(v) (((v) + 31) & -32)
-#define down32(v) ((v) & -32)
-#define div32(v) ((v)>>5)
-#define mod32(v) ((v) & 31)
-
-#define up64(v) (((v) + 63) & -64)
-#define down64(v) ((v) & -64)
-#define div64(v) ((v)>>6)
-#define mod64(v) ((v) & 63)
-
-#define upx(x, v) (((v) + (x) - 1) & -(x))
-#define downx(x, v) ((v) & -(x))
-#define modx(x, v) ((v) & ((x) - 1))
-
-/*
- * FIXME: Use C variants of the code marked with #ifdef __mc68000__
- * in the driver. It shouldn't negatively affect the performance and
- * is required for APUS support (once it is re-added to the kernel).
- * Needs to be tested on the hardware though..
- */
-/* if x1 is not a constant, this macro won't make real sense :-) */
-#ifdef __mc68000__
-#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
- "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
-#else
-/* We know a bit about the numbers, so we can do it this way */
-#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
- ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
-#endif
-
-#define highw(x) ((u_long)(x)>>16 & 0xffff)
-#define loww(x) ((u_long)(x) & 0xffff)
-
-#define custom amiga_custom
-
-#define VBlankOn() custom.intena = IF_SETCLR|IF_COPER
-#define VBlankOff() custom.intena = IF_COPER
-
-
- /*
- * Chip RAM we reserve for the Frame Buffer
- *
- * This defines the Maximum Virtual Screen Size
- * (Setable per kernel options?)
- */
-
-#define VIDEOMEMSIZE_AGA_2M (1310720) /* AGA (2MB) : max 1280*1024*256 */
-#define VIDEOMEMSIZE_AGA_1M (786432) /* AGA (1MB) : max 1024*768*256 */
-#define VIDEOMEMSIZE_ECS_2M (655360) /* ECS (2MB) : max 1280*1024*16 */
-#define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */
-#define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */
-
-#define SPRITEMEMSIZE (64 * 64 / 4) /* max 64*64*4 */
-#define DUMMYSPRITEMEMSIZE (8)
-static u_long spritememory;
-
-#define CHIPRAM_SAFETY_LIMIT (16384)
-
-static u_long videomemory;
-
- /*
- * This is the earliest allowed start of fetching display data.
- * Only if you really want no hardware cursor and audio,
- * set this to 128, but let it better at 192
- */
-
-static u_long min_fstrt = 192;
-
-#define assignchunk(name, type, ptr, size) \
-{ \
- (name) = (type)(ptr); \
- ptr += size; \
-}
-
-
- /*
- * Copper Instructions
- */
-
-#define CMOVE(val, reg) (CUSTOM_OFS(reg) << 16 | (val))
-#define CMOVE2(val, reg) ((CUSTOM_OFS(reg) + 2) << 16 | (val))
-#define CWAIT(x, y) (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
-#define CEND (0xfffffffe)
-
-
-typedef union {
- u_long l;
- u_short w[2];
-} copins;
-
-static struct copdisplay {
- copins *init;
- copins *wait;
- copins *list[2][2];
- copins *rebuild[2];
-} copdisplay;
-
-static u_short currentcop = 0;
-
- /*
- * Hardware Cursor API Definitions
- * These used to be in linux/fb.h, but were preliminary and used by
- * amifb only anyway
- */
-
-#define FBIOGET_FCURSORINFO 0x4607
-#define FBIOGET_VCURSORINFO 0x4608
-#define FBIOPUT_VCURSORINFO 0x4609
-#define FBIOGET_CURSORSTATE 0x460A
-#define FBIOPUT_CURSORSTATE 0x460B
-
-
-struct fb_fix_cursorinfo {
- __u16 crsr_width; /* width and height of the cursor in */
- __u16 crsr_height; /* pixels (zero if no cursor) */
- __u16 crsr_xsize; /* cursor size in display pixels */
- __u16 crsr_ysize;
- __u16 crsr_color1; /* colormap entry for cursor color1 */
- __u16 crsr_color2; /* colormap entry for cursor color2 */
-};
-
-struct fb_var_cursorinfo {
- __u16 width;
- __u16 height;
- __u16 xspot;
- __u16 yspot;
- DECLARE_FLEX_ARRAY(__u8, data); /* field with [height][width] */
-};
-
-struct fb_cursorstate {
- __s16 xoffset;
- __s16 yoffset;
- __u16 mode;
-};
-
-#define FB_CURSOR_OFF 0
-#define FB_CURSOR_ON 1
-#define FB_CURSOR_FLASH 2
-
-
- /*
- * Hardware Cursor
- */
-
-static int cursorrate = 20; /* Number of frames/flash toggle */
-static u_short cursorstate = -1;
-static u_short cursormode = FB_CURSOR_OFF;
-
-static u_short *lofsprite, *shfsprite, *dummysprite;
-
- /*
- * Current Video Mode
- */
-
-struct amifb_par {
-
- /* General Values */
-
- int xres; /* vmode */
- int yres; /* vmode */
- int vxres; /* vmode */
- int vyres; /* vmode */
- int xoffset; /* vmode */
- int yoffset; /* vmode */
- u_short bpp; /* vmode */
- u_short clk_shift; /* vmode */
- u_short line_shift; /* vmode */
- int vmode; /* vmode */
- u_short diwstrt_h; /* vmode */
- u_short diwstop_h; /* vmode */
- u_short diwstrt_v; /* vmode */
- u_short diwstop_v; /* vmode */
- u_long next_line; /* modulo for next line */
- u_long next_plane; /* modulo for next plane */
-
- /* Cursor Values */
-
- struct {
- short crsr_x; /* movecursor */
- short crsr_y; /* movecursor */
- short spot_x;
- short spot_y;
- u_short height;
- u_short width;
- u_short fmode;
- } crsr;
-
- /* OCS Hardware Registers */
-
- u_long bplpt0; /* vmode, pan (Note: physical address) */
- u_long bplpt0wrap; /* vmode, pan (Note: physical address) */
- u_short ddfstrt;
- u_short ddfstop;
- u_short bpl1mod;
- u_short bpl2mod;
- u_short bplcon0; /* vmode */
- u_short bplcon1; /* vmode */
- u_short htotal; /* vmode */
- u_short vtotal; /* vmode */
-
- /* Additional ECS Hardware Registers */
-
- u_short bplcon3; /* vmode */
- u_short beamcon0; /* vmode */
- u_short hsstrt; /* vmode */
- u_short hsstop; /* vmode */
- u_short hbstrt; /* vmode */
- u_short hbstop; /* vmode */
- u_short vsstrt; /* vmode */
- u_short vsstop; /* vmode */
- u_short vbstrt; /* vmode */
- u_short vbstop; /* vmode */
- u_short hcenter; /* vmode */
-
- /* Additional AGA Hardware Registers */
-
- u_short fmode; /* vmode */
-};
-
-
- /*
- * Saved color entry 0 so we can restore it when unblanking
- */
-
-static u_char red0, green0, blue0;
-
-
-#if defined(CONFIG_FB_AMIGA_ECS)
-static u_short ecs_palette[32];
-#endif
-
-
- /*
- * Latches for Display Changes during VBlank
- */
-
-static u_short do_vmode_full = 0; /* Change the Video Mode */
-static u_short do_vmode_pan = 0; /* Update the Video Mode */
-static short do_blank = 0; /* (Un)Blank the Screen (±1) */
-static u_short do_cursor = 0; /* Move the Cursor */
-
-
- /*
- * Various Flags
- */
-
-static u_short is_blanked = 0; /* Screen is Blanked */
-static u_short is_lace = 0; /* Screen is laced */
-
- /*
- * Predefined Video Modes
- *
- */
-
-static struct fb_videomode ami_modedb[] __initdata = {
-
- /*
- * AmigaOS Video Modes
- *
- * If you change these, make sure to update DEFMODE_* as well!
- */
-
- {
- /* 640x200, 15 kHz, 60 Hz (NTSC) */
- "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
- FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
- "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
- FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x256, 15 kHz, 50 Hz (PAL) */
- "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
- FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
- "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
- FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x480, 29 kHz, 57 Hz */
- "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x960, 29 kHz, 57 Hz interlaced */
- "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
- 16,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x200, 15 kHz, 72 Hz */
- "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x400, 15 kHz, 72 Hz interlaced */
- "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
- 10,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x400, 29 kHz, 68 Hz */
- "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x800, 29 kHz, 68 Hz interlaced */
- "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
- 16,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 800x300, 23 kHz, 70 Hz */
- "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 800x600, 23 kHz, 70 Hz interlaced */
- "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
- 14,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x200, 27 kHz, 57 Hz doublescan */
- "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
- 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
- }, {
- /* 640x400, 27 kHz, 57 Hz */
- "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x800, 27 kHz, 57 Hz interlaced */
- "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
- 14,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x256, 27 kHz, 47 Hz doublescan */
- "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
- 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
- }, {
- /* 640x512, 27 kHz, 47 Hz */
- "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x1024, 27 kHz, 47 Hz interlaced */
- "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
- 14,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- },
-
- /*
- * VGA Video Modes
- */
-
- {
- /* 640x480, 31 kHz, 60 Hz (VGA) */
- "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x400, 31 kHz, 70 Hz (VGA) */
- "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
- FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
- FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- },
-
-#if 0
-
- /*
- * A2024 video modes
- * These modes don't work yet because there's no A2024 driver.
- */
-
- {
- /* 1024x800, 10 Hz */
- "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 1024x800, 15 Hz */
- "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }
-#endif
-};
-
-#define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb)
-
-static char *mode_option __initdata = NULL;
-static int round_down_bpp = 1; /* for mode probing */
-
- /*
- * Some default modes
- */
-
-
-#define DEFMODE_PAL 2 /* "pal" for PAL OCS/ECS */
-#define DEFMODE_NTSC 0 /* "ntsc" for NTSC OCS/ECS */
-#define DEFMODE_AMBER_PAL 3 /* "pal-lace" for flicker fixed PAL (A3000) */
-#define DEFMODE_AMBER_NTSC 1 /* "ntsc-lace" for flicker fixed NTSC (A3000) */
-#define DEFMODE_AGA 19 /* "vga70" for AGA */
-
-
-static int amifb_ilbm = 0; /* interleaved or normal bitplanes */
-
-static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */
-static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */
-static u16 amifb_vfmin __initdata; /* monitor vfreq lower limit (Hz) */
-static u16 amifb_vfmax __initdata; /* monitor vfreq upper limit (Hz) */
-
-
- /*
- * Macros for the conversion from real world values to hardware register
- * values
- *
- * This helps us to keep our attention on the real stuff...
- *
- * Hardware limits for AGA:
- *
- * parameter min max step
- * --------- --- ---- ----
- * diwstrt_h 0 2047 1
- * diwstrt_v 0 2047 1
- * diwstop_h 0 4095 1
- * diwstop_v 0 4095 1
- *
- * ddfstrt 0 2032 16
- * ddfstop 0 2032 16
- *
- * htotal 8 2048 8
- * hsstrt 0 2040 8
- * hsstop 0 2040 8
- * vtotal 1 4096 1
- * vsstrt 0 4095 1
- * vsstop 0 4095 1
- * hcenter 0 2040 8
- *
- * hbstrt 0 2047 1
- * hbstop 0 2047 1
- * vbstrt 0 4095 1
- * vbstop 0 4095 1
- *
- * Horizontal values are in 35 ns (SHRES) pixels
- * Vertical values are in half scanlines
- */
-
-/* bplcon1 (smooth scrolling) */
-
-#define hscroll2hw(hscroll) \
- (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
- ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
- ((hscroll)>>2 & 0x000f))
-
-/* diwstrt/diwstop/diwhigh (visible display window) */
-
-#define diwstrt2hw(diwstrt_h, diwstrt_v) \
- (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
-#define diwstop2hw(diwstop_h, diwstop_v) \
- (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
-#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
- (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
- ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
- ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
-
-/* ddfstrt/ddfstop (display DMA) */
-
-#define ddfstrt2hw(ddfstrt) div8(ddfstrt)
-#define ddfstop2hw(ddfstop) div8(ddfstop)
-
-/* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal/hcenter (sync timings) */
-
-#define hsstrt2hw(hsstrt) (div8(hsstrt))
-#define hsstop2hw(hsstop) (div8(hsstop))
-#define htotal2hw(htotal) (div8(htotal) - 1)
-#define vsstrt2hw(vsstrt) (div2(vsstrt))
-#define vsstop2hw(vsstop) (div2(vsstop))
-#define vtotal2hw(vtotal) (div2(vtotal) - 1)
-#define hcenter2hw(htotal) (div8(htotal))
-
-/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
-
-#define hbstrt2hw(hbstrt) (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
-#define hbstop2hw(hbstop) (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
-#define vbstrt2hw(vbstrt) (div2(vbstrt))
-#define vbstop2hw(vbstop) (div2(vbstop))
-
-/* colour */
-
-#define rgb2hw8_high(red, green, blue) \
- (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
-#define rgb2hw8_low(red, green, blue) \
- (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
-#define rgb2hw4(red, green, blue) \
- (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
-#define rgb2hw2(red, green, blue) \
- (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
-
-/* sprpos/sprctl (sprite positioning) */
-
-#define spr2hw_pos(start_v, start_h) \
- (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
-#define spr2hw_ctl(start_v, start_h, stop_v) \
- (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
- ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
- ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
- ((start_h)>>2 & 0x0001))
-
-/* get current vertical position of beam */
-#define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
-
- /*
- * Copper Initialisation List
- */
-
-#define COPINITSIZE (sizeof(copins) * 40)
-
-enum {
- cip_bplcon0
-};
-
- /*
- * Long Frame/Short Frame Copper List
- * Don't change the order, build_copper()/rebuild_copper() rely on this
- */
-
-#define COPLISTSIZE (sizeof(copins) * 64)
-
-enum {
- cop_wait, cop_bplcon0,
- cop_spr0ptrh, cop_spr0ptrl,
- cop_diwstrt, cop_diwstop,
- cop_diwhigh,
-};
-
- /*
- * Pixel modes for Bitplanes and Sprites
- */
-
-static u_short bplpixmode[3] = {
- BPC0_SHRES, /* 35 ns */
- BPC0_HIRES, /* 70 ns */
- 0 /* 140 ns */
-};
-
-static u_short sprpixmode[3] = {
- BPC3_SPRES1 | BPC3_SPRES0, /* 35 ns */
- BPC3_SPRES1, /* 70 ns */
- BPC3_SPRES0 /* 140 ns */
-};
-
- /*
- * Fetch modes for Bitplanes and Sprites
- */
-
-static u_short bplfetchmode[3] = {
- 0, /* 1x */
- FMODE_BPL32, /* 2x */
- FMODE_BPAGEM | FMODE_BPL32 /* 4x */
-};
-
-static u_short sprfetchmode[3] = {
- 0, /* 1x */
- FMODE_SPR32, /* 2x */
- FMODE_SPAGEM | FMODE_SPR32 /* 4x */
-};
-
-
-/* --------------------------- Hardware routines --------------------------- */
-
- /*
- * Get the video params out of `var'. If a value doesn't fit, round
- * it up, if it's too big, return -EINVAL.
- */
-
-static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
- const struct fb_info *info)
-{
- u_short clk_shift, line_shift;
- u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
- u_int htotal, vtotal;
-
- /*
- * Find a matching Pixel Clock
- */
-
- for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
- if (var->pixclock <= pixclock[clk_shift])
- break;
- if (clk_shift > TAG_LORES) {
- DPRINTK("pixclock too high\n");
- return -EINVAL;
- }
- par->clk_shift = clk_shift;
-
- /*
- * Check the Geometry Values
- */
-
- if ((par->xres = var->xres) < 64)
- par->xres = 64;
- if ((par->yres = var->yres) < 64)
- par->yres = 64;
- if ((par->vxres = var->xres_virtual) < par->xres)
- par->vxres = par->xres;
- if ((par->vyres = var->yres_virtual) < par->yres)
- par->vyres = par->yres;
-
- par->bpp = var->bits_per_pixel;
- if (!var->nonstd) {
- if (par->bpp < 1)
- par->bpp = 1;
- if (par->bpp > maxdepth[clk_shift]) {
- if (round_down_bpp && maxdepth[clk_shift])
- par->bpp = maxdepth[clk_shift];
- else {
- DPRINTK("invalid bpp\n");
- return -EINVAL;
- }
- }
- } else if (var->nonstd == FB_NONSTD_HAM) {
- if (par->bpp < 6)
- par->bpp = 6;
- if (par->bpp != 6) {
- if (par->bpp < 8)
- par->bpp = 8;
- if (par->bpp != 8 || !IS_AGA) {
- DPRINTK("invalid bpp for ham mode\n");
- return -EINVAL;
- }
- }
- } else {
- DPRINTK("unknown nonstd mode\n");
- return -EINVAL;
- }
-
- /*
- * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the following
- * checks failed and smooth scrolling is not possible
- */
-
- par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
- switch (par->vmode & FB_VMODE_MASK) {
- case FB_VMODE_INTERLACED:
- line_shift = 0;
- break;
- case FB_VMODE_NONINTERLACED:
- line_shift = 1;
- break;
- case FB_VMODE_DOUBLE:
- if (!IS_AGA) {
- DPRINTK("double mode only possible with aga\n");
- return -EINVAL;
- }
- line_shift = 2;
- break;
- default:
- DPRINTK("unknown video mode\n");
- return -EINVAL;
- break;
- }
- par->line_shift = line_shift;
-
- /*
- * Vertical and Horizontal Timings
- */
-
- xres_n = par->xres << clk_shift;
- yres_n = par->yres << line_shift;
- par->htotal = down8((var->left_margin + par->xres + var->right_margin +
- var->hsync_len) << clk_shift);
- par->vtotal =
- down2(((var->upper_margin + par->yres + var->lower_margin +
- var->vsync_len) << line_shift) + 1);
-
- if (IS_AGA)
- par->bplcon3 = sprpixmode[clk_shift];
- else
- par->bplcon3 = 0;
- if (var->sync & FB_SYNC_BROADCAST) {
- par->diwstop_h = par->htotal -
- ((var->right_margin - var->hsync_len) << clk_shift);
- if (IS_AGA)
- par->diwstop_h += mod4(var->hsync_len);
- else
- par->diwstop_h = down4(par->diwstop_h);
-
- par->diwstrt_h = par->diwstop_h - xres_n;
- par->diwstop_v = par->vtotal -
- ((var->lower_margin - var->vsync_len) << line_shift);
- par->diwstrt_v = par->diwstop_v - yres_n;
- if (par->diwstop_h >= par->htotal + 8) {
- DPRINTK("invalid diwstop_h\n");
- return -EINVAL;
- }
- if (par->diwstop_v > par->vtotal) {
- DPRINTK("invalid diwstop_v\n");
- return -EINVAL;
- }
-
- if (!IS_OCS) {
- /* Initialize sync with some reasonable values for pwrsave */
- par->hsstrt = 160;
- par->hsstop = 320;
- par->vsstrt = 30;
- par->vsstop = 34;
- } else {
- par->hsstrt = 0;
- par->hsstop = 0;
- par->vsstrt = 0;
- par->vsstop = 0;
- }
- if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
- /* PAL video mode */
- if (par->htotal != PAL_HTOTAL) {
- DPRINTK("htotal invalid for pal\n");
- return -EINVAL;
- }
- if (par->diwstrt_h < PAL_DIWSTRT_H) {
- DPRINTK("diwstrt_h too low for pal\n");
- return -EINVAL;
- }
- if (par->diwstrt_v < PAL_DIWSTRT_V) {
- DPRINTK("diwstrt_v too low for pal\n");
- return -EINVAL;
- }
- htotal = PAL_HTOTAL>>clk_shift;
- vtotal = PAL_VTOTAL>>1;
- if (!IS_OCS) {
- par->beamcon0 = BMC0_PAL;
- par->bplcon3 |= BPC3_BRDRBLNK;
- } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
- AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
- par->beamcon0 = BMC0_PAL;
- par->hsstop = 1;
- } else if (amiga_vblank != 50) {
- DPRINTK("pal not supported by this chipset\n");
- return -EINVAL;
- }
- } else {
- /* NTSC video mode
- * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
- * and NTSC activated, so than better let diwstop_h <= 1812
- */
- if (par->htotal != NTSC_HTOTAL) {
- DPRINTK("htotal invalid for ntsc\n");
- return -EINVAL;
- }
- if (par->diwstrt_h < NTSC_DIWSTRT_H) {
- DPRINTK("diwstrt_h too low for ntsc\n");
- return -EINVAL;
- }
- if (par->diwstrt_v < NTSC_DIWSTRT_V) {
- DPRINTK("diwstrt_v too low for ntsc\n");
- return -EINVAL;
- }
- htotal = NTSC_HTOTAL>>clk_shift;
- vtotal = NTSC_VTOTAL>>1;
- if (!IS_OCS) {
- par->beamcon0 = 0;
- par->bplcon3 |= BPC3_BRDRBLNK;
- } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
- AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
- par->beamcon0 = 0;
- par->hsstop = 1;
- } else if (amiga_vblank != 60) {
- DPRINTK("ntsc not supported by this chipset\n");
- return -EINVAL;
- }
- }
- if (IS_OCS) {
- if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
- par->diwstrt_v >= 512 || par->diwstop_v < 256) {
- DPRINTK("invalid position for display on ocs\n");
- return -EINVAL;
- }
- }
- } else if (!IS_OCS) {
- /* Programmable video mode */
- par->hsstrt = var->right_margin << clk_shift;
- par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
- par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
- if (!IS_AGA)
- par->diwstop_h = down4(par->diwstop_h) - 16;
- par->diwstrt_h = par->diwstop_h - xres_n;
- par->hbstop = par->diwstrt_h + 4;
- par->hbstrt = par->diwstop_h + 4;
- if (par->hbstrt >= par->htotal + 8)
- par->hbstrt -= par->htotal;
- par->hcenter = par->hsstrt + (par->htotal >> 1);
- par->vsstrt = var->lower_margin << line_shift;
- par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
- par->diwstop_v = par->vtotal;
- if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
- par->diwstop_v -= 2;
- par->diwstrt_v = par->diwstop_v - yres_n;
- par->vbstop = par->diwstrt_v - 2;
- par->vbstrt = par->diwstop_v - 2;
- if (par->vtotal > 2048) {
- DPRINTK("vtotal too high\n");
- return -EINVAL;
- }
- if (par->htotal > 2048) {
- DPRINTK("htotal too high\n");
- return -EINVAL;
- }
- par->bplcon3 |= BPC3_EXTBLKEN;
- par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
- BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
- BMC0_PAL | BMC0_VARCSYEN;
- if (var->sync & FB_SYNC_HOR_HIGH_ACT)
- par->beamcon0 |= BMC0_HSYTRUE;
- if (var->sync & FB_SYNC_VERT_HIGH_ACT)
- par->beamcon0 |= BMC0_VSYTRUE;
- if (var->sync & FB_SYNC_COMP_HIGH_ACT)
- par->beamcon0 |= BMC0_CSYTRUE;
- htotal = par->htotal>>clk_shift;
- vtotal = par->vtotal>>1;
- } else {
- DPRINTK("only broadcast modes possible for ocs\n");
- return -EINVAL;
- }
-
- /*
- * Checking the DMA timing
- */
-
- fconst = 16 << maxfmode << clk_shift;
-
- /*
- * smallest window start value without turn off other dma cycles
- * than sprite1-7, unless you change min_fstrt
- */
-
-
- fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
- fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
- if (fstrt < min_fstrt) {
- DPRINTK("fetch start too low\n");
- return -EINVAL;
- }
-
- /*
- * smallest window start value where smooth scrolling is possible
- */
-
- fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
- fsize;
- if (fstrt < min_fstrt)
- par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
- maxfetchstop = down16(par->htotal - 80);
-
- fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
- fsize = upx(fconst, xres_n +
- modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
- if (fstrt + fsize > maxfetchstop)
- par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
- fsize = upx(fconst, xres_n);
- if (fstrt + fsize > maxfetchstop) {
- DPRINTK("fetch stop too high\n");
- return -EINVAL;
- }
-
- if (maxfmode + clk_shift <= 1) {
- fsize = up64(xres_n + fconst - 1);
- if (min_fstrt + fsize - 64 > maxfetchstop)
- par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
- fsize = up64(xres_n);
- if (min_fstrt + fsize - 64 > maxfetchstop) {
- DPRINTK("fetch size too high\n");
- return -EINVAL;
- }
-
- fsize -= 64;
- } else
- fsize -= fconst;
-
- /*
- * Check if there is enough time to update the bitplane pointers for ywrap
- */
-
- if (par->htotal - fsize - 64 < par->bpp * 64)
- par->vmode &= ~FB_VMODE_YWRAP;
-
- /*
- * Bitplane calculations and check the Memory Requirements
- */
-
- if (amifb_ilbm) {
- par->next_plane = div8(upx(16 << maxfmode, par->vxres));
- par->next_line = par->bpp * par->next_plane;
- if (par->next_line * par->vyres > info->fix.smem_len) {
- DPRINTK("too few video mem\n");
- return -EINVAL;
- }
- } else {
- par->next_line = div8(upx(16 << maxfmode, par->vxres));
- par->next_plane = par->vyres * par->next_line;
- if (par->next_plane * par->bpp > info->fix.smem_len) {
- DPRINTK("too few video mem\n");
- return -EINVAL;
- }
- }
-
- /*
- * Hardware Register Values
- */
-
- par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
- if (!IS_OCS)
- par->bplcon0 |= BPC0_ECSENA;
- if (par->bpp == 8)
- par->bplcon0 |= BPC0_BPU3;
- else
- par->bplcon0 |= par->bpp << 12;
- if (var->nonstd == FB_NONSTD_HAM)
- par->bplcon0 |= BPC0_HAM;
- if (var->sync & FB_SYNC_EXT)
- par->bplcon0 |= BPC0_ERSY;
-
- if (IS_AGA)
- par->fmode = bplfetchmode[maxfmode];
-
- switch (par->vmode & FB_VMODE_MASK) {
- case FB_VMODE_INTERLACED:
- par->bplcon0 |= BPC0_LACE;
- break;
- case FB_VMODE_DOUBLE:
- if (IS_AGA)
- par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
- break;
- }
-
- if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
- par->xoffset = var->xoffset;
- par->yoffset = var->yoffset;
- if (par->vmode & FB_VMODE_YWRAP) {
- if (par->yoffset >= par->vyres)
- par->xoffset = par->yoffset = 0;
- } else {
- if (par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
- par->yoffset > par->vyres - par->yres)
- par->xoffset = par->yoffset = 0;
- }
- } else
- par->xoffset = par->yoffset = 0;
-
- par->crsr.crsr_x = par->crsr.crsr_y = 0;
- par->crsr.spot_x = par->crsr.spot_y = 0;
- par->crsr.height = par->crsr.width = 0;
-
- return 0;
-}
-
- /*
- * Fill the `var' structure based on the values in `par' and maybe
- * other values read out of the hardware.
- */
-
-static void ami_encode_var(struct fb_var_screeninfo *var,
- struct amifb_par *par)
-{
- u_short clk_shift, line_shift;
-
- memset(var, 0, sizeof(struct fb_var_screeninfo));
-
- clk_shift = par->clk_shift;
- line_shift = par->line_shift;
-
- var->xres = par->xres;
- var->yres = par->yres;
- var->xres_virtual = par->vxres;
- var->yres_virtual = par->vyres;
- var->xoffset = par->xoffset;
- var->yoffset = par->yoffset;
-
- var->bits_per_pixel = par->bpp;
- var->grayscale = 0;
-
- var->red.offset = 0;
- var->red.msb_right = 0;
- var->red.length = par->bpp;
- if (par->bplcon0 & BPC0_HAM)
- var->red.length -= 2;
- var->blue = var->green = var->red;
- var->transp.offset = 0;
- var->transp.length = 0;
- var->transp.msb_right = 0;
-
- if (par->bplcon0 & BPC0_HAM)
- var->nonstd = FB_NONSTD_HAM;
- else
- var->nonstd = 0;
- var->activate = 0;
-
- var->height = -1;
- var->width = -1;
-
- var->pixclock = pixclock[clk_shift];
-
- if (IS_AGA && par->fmode & FMODE_BSCAN2)
- var->vmode = FB_VMODE_DOUBLE;
- else if (par->bplcon0 & BPC0_LACE)
- var->vmode = FB_VMODE_INTERLACED;
- else
- var->vmode = FB_VMODE_NONINTERLACED;
-
- if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
- var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
- var->right_margin = par->hsstrt>>clk_shift;
- var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
- var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
- var->lower_margin = par->vsstrt>>line_shift;
- var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
- var->sync = 0;
- if (par->beamcon0 & BMC0_HSYTRUE)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (par->beamcon0 & BMC0_VSYTRUE)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
- if (par->beamcon0 & BMC0_CSYTRUE)
- var->sync |= FB_SYNC_COMP_HIGH_ACT;
- } else {
- var->sync = FB_SYNC_BROADCAST;
- var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
- var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
- var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
- var->vsync_len = 4>>line_shift;
- var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
- var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
- var->lower_margin - var->vsync_len;
- }
-
- if (par->bplcon0 & BPC0_ERSY)
- var->sync |= FB_SYNC_EXT;
- if (par->vmode & FB_VMODE_YWRAP)
- var->vmode |= FB_VMODE_YWRAP;
-}
-
-
- /*
- * Update hardware
- */
-
-static void ami_update_par(struct fb_info *info)
-{
- struct amifb_par *par = info->par;
- short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
-
- clk_shift = par->clk_shift;
-
- if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
- par->xoffset = upx(16 << maxfmode, par->xoffset);
-
- fconst = 16 << maxfmode << clk_shift;
- vshift = modx(16 << maxfmode, par->xoffset);
- fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
- fsize = (par->xres + vshift) << clk_shift;
- shift = modx(fconst, fstrt);
- move = downx(2 << maxfmode, div8(par->xoffset));
- if (maxfmode + clk_shift > 1) {
- fstrt = downx(fconst, fstrt) - 64;
- fsize = upx(fconst, fsize);
- fstop = fstrt + fsize - fconst;
- } else {
- mod = fstrt = downx(fconst, fstrt) - fconst;
- fstop = fstrt + upx(fconst, fsize) - 64;
- fsize = up64(fsize);
- fstrt = fstop - fsize + 64;
- if (fstrt < min_fstrt) {
- fstop += min_fstrt - fstrt;
- fstrt = min_fstrt;
- }
- move = move - div8((mod - fstrt)>>clk_shift);
- }
- mod = par->next_line - div8(fsize>>clk_shift);
- par->ddfstrt = fstrt;
- par->ddfstop = fstop;
- par->bplcon1 = hscroll2hw(shift);
- par->bpl2mod = mod;
- if (par->bplcon0 & BPC0_LACE)
- par->bpl2mod += par->next_line;
- if (IS_AGA && (par->fmode & FMODE_BSCAN2))
- par->bpl1mod = -div8(fsize>>clk_shift);
- else
- par->bpl1mod = par->bpl2mod;
-
- if (par->yoffset) {
- par->bplpt0 = info->fix.smem_start +
- par->next_line * par->yoffset + move;
- if (par->vmode & FB_VMODE_YWRAP) {
- if (par->yoffset > par->vyres - par->yres) {
- par->bplpt0wrap = info->fix.smem_start + move;
- if (par->bplcon0 & BPC0_LACE &&
- mod2(par->diwstrt_v + par->vyres -
- par->yoffset))
- par->bplpt0wrap += par->next_line;
- }
- }
- } else
- par->bplpt0 = info->fix.smem_start + move;
-
- if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
- par->bplpt0 += par->next_line;
-}
-
-
- /*
- * Pan or Wrap the Display
- *
- * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- * in `var'.
- */
-
-static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct amifb_par *par = info->par;
-
- par->xoffset = var->xoffset;
- par->yoffset = var->yoffset;
- if (var->vmode & FB_VMODE_YWRAP)
- par->vmode |= FB_VMODE_YWRAP;
- else
- par->vmode &= ~FB_VMODE_YWRAP;
-
- do_vmode_pan = 0;
- ami_update_par(info);
- do_vmode_pan = 1;
-}
-
-
-static void ami_update_display(const struct amifb_par *par)
-{
- custom.bplcon1 = par->bplcon1;
- custom.bpl1mod = par->bpl1mod;
- custom.bpl2mod = par->bpl2mod;
- custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
- custom.ddfstop = ddfstop2hw(par->ddfstop);
-}
-
- /*
- * Change the video mode (called by VBlank interrupt)
- */
-
-static void ami_init_display(const struct amifb_par *par)
-{
- int i;
-
- custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
- custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
- if (!IS_OCS) {
- custom.bplcon3 = par->bplcon3;
- if (IS_AGA)
- custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
- if (par->beamcon0 & BMC0_VARBEAMEN) {
- custom.htotal = htotal2hw(par->htotal);
- custom.hbstrt = hbstrt2hw(par->hbstrt);
- custom.hbstop = hbstop2hw(par->hbstop);
- custom.hsstrt = hsstrt2hw(par->hsstrt);
- custom.hsstop = hsstop2hw(par->hsstop);
- custom.hcenter = hcenter2hw(par->hcenter);
- custom.vtotal = vtotal2hw(par->vtotal);
- custom.vbstrt = vbstrt2hw(par->vbstrt);
- custom.vbstop = vbstop2hw(par->vbstop);
- custom.vsstrt = vsstrt2hw(par->vsstrt);
- custom.vsstop = vsstop2hw(par->vsstop);
- }
- }
- if (!IS_OCS || par->hsstop)
- custom.beamcon0 = par->beamcon0;
- if (IS_AGA)
- custom.fmode = par->fmode;
-
- /*
- * The minimum period for audio depends on htotal
- */
-
- amiga_audio_min_period = div16(par->htotal);
-
- is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
-#if 1
- if (is_lace) {
- i = custom.vposr >> 15;
- } else {
- custom.vposw = custom.vposr | 0x8000;
- i = 1;
- }
-#else
- i = 1;
- custom.vposw = custom.vposr | 0x8000;
-#endif
- custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
-}
-
- /*
- * (Un)Blank the screen (called by VBlank interrupt)
- */
-
-static void ami_do_blank(const struct amifb_par *par)
-{
-#if defined(CONFIG_FB_AMIGA_AGA)
- u_short bplcon3 = par->bplcon3;
-#endif
- u_char red, green, blue;
-
- if (do_blank > 0) {
- custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
- red = green = blue = 0;
- if (!IS_OCS && do_blank > 1) {
- switch (do_blank) {
- case FB_BLANK_VSYNC_SUSPEND:
- custom.hsstrt = hsstrt2hw(par->hsstrt);
- custom.hsstop = hsstop2hw(par->hsstop);
- custom.vsstrt = vsstrt2hw(par->vtotal + 4);
- custom.vsstop = vsstop2hw(par->vtotal + 4);
- break;
- case FB_BLANK_HSYNC_SUSPEND:
- custom.hsstrt = hsstrt2hw(par->htotal + 16);
- custom.hsstop = hsstop2hw(par->htotal + 16);
- custom.vsstrt = vsstrt2hw(par->vsstrt);
- custom.vsstop = vsstrt2hw(par->vsstop);
- break;
- case FB_BLANK_POWERDOWN:
- custom.hsstrt = hsstrt2hw(par->htotal + 16);
- custom.hsstop = hsstop2hw(par->htotal + 16);
- custom.vsstrt = vsstrt2hw(par->vtotal + 4);
- custom.vsstop = vsstop2hw(par->vtotal + 4);
- break;
- }
- if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
- custom.htotal = htotal2hw(par->htotal);
- custom.vtotal = vtotal2hw(par->vtotal);
- custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
- BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
- }
- }
- } else {
- custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
- red = red0;
- green = green0;
- blue = blue0;
- if (!IS_OCS) {
- custom.hsstrt = hsstrt2hw(par->hsstrt);
- custom.hsstop = hsstop2hw(par->hsstop);
- custom.vsstrt = vsstrt2hw(par->vsstrt);
- custom.vsstop = vsstop2hw(par->vsstop);
- custom.beamcon0 = par->beamcon0;
- }
- }
-#if defined(CONFIG_FB_AMIGA_AGA)
- if (IS_AGA) {
- custom.bplcon3 = bplcon3;
- custom.color[0] = rgb2hw8_high(red, green, blue);
- custom.bplcon3 = bplcon3 | BPC3_LOCT;
- custom.color[0] = rgb2hw8_low(red, green, blue);
- custom.bplcon3 = bplcon3;
- } else
-#endif
-#if defined(CONFIG_FB_AMIGA_ECS)
- if (par->bplcon0 & BPC0_SHRES) {
- u_short color, mask;
- int i;
-
- mask = 0x3333;
- color = rgb2hw2(red, green, blue);
- for (i = 12; i >= 0; i -= 4)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- mask <<= 2; color >>= 2;
- for (i = 3; i >= 0; i--)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- } else
-#endif
- custom.color[0] = rgb2hw4(red, green, blue);
- is_blanked = do_blank > 0 ? do_blank : 0;
-}
-
-static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
- const struct amifb_par *par)
-{
- fix->crsr_width = fix->crsr_xsize = par->crsr.width;
- fix->crsr_height = fix->crsr_ysize = par->crsr.height;
- fix->crsr_color1 = 17;
- fix->crsr_color2 = 18;
- return 0;
-}
-
-static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
- u_char __user *data,
- const struct amifb_par *par)
-{
- register u_short *lspr, *sspr;
-#ifdef __mc68000__
- register u_long datawords asm ("d2");
-#else
- register u_long datawords;
-#endif
- register short delta;
- register u_char color;
- short height, width, bits, words;
- int size, alloc;
-
- size = par->crsr.height * par->crsr.width;
- alloc = var->height * var->width;
- var->height = par->crsr.height;
- var->width = par->crsr.width;
- var->xspot = par->crsr.spot_x;
- var->yspot = par->crsr.spot_y;
- if (size > var->height * var->width)
- return -ENAMETOOLONG;
- delta = 1 << par->crsr.fmode;
- lspr = lofsprite + (delta << 1);
- if (par->bplcon0 & BPC0_LACE)
- sspr = shfsprite + (delta << 1);
- else
- sspr = NULL;
- for (height = (short)var->height - 1; height >= 0; height--) {
- bits = 0; words = delta; datawords = 0;
- for (width = (short)var->width - 1; width >= 0; width--) {
- if (bits == 0) {
- bits = 16; --words;
-#ifdef __mc68000__
- asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
- : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
-#else
- datawords = (*(lspr + delta) << 16) | (*lspr++);
-#endif
- }
- --bits;
-#ifdef __mc68000__
- asm volatile (
- "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
- "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
- : "=d" (color), "=d" (datawords) : "1" (datawords));
-#else
- color = (((datawords >> 30) & 2)
- | ((datawords >> 15) & 1));
- datawords <<= 1;
-#endif
- /* FIXME: check the return value + test the change */
- put_user(color, data++);
- }
- if (bits > 0) {
- --words; ++lspr;
- }
- while (--words >= 0)
- ++lspr;
-#ifdef __mc68000__
- asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
- : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
-#else
- lspr += delta;
- if (sspr) {
- u_short *tmp = lspr;
- lspr = sspr;
- sspr = tmp;
- }
-#endif
- }
- return 0;
-}
-
-static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
- u_char __user *data, struct amifb_par *par)
-{
- register u_short *lspr, *sspr;
-#ifdef __mc68000__
- register u_long datawords asm ("d2");
-#else
- register u_long datawords;
-#endif
- register short delta;
- u_short fmode;
- short height, width, bits, words;
-
- if (!var->width)
- return -EINVAL;
- else if (var->width <= 16)
- fmode = TAG_FMODE_1;
- else if (var->width <= 32)
- fmode = TAG_FMODE_2;
- else if (var->width <= 64)
- fmode = TAG_FMODE_4;
- else
- return -EINVAL;
- if (fmode > maxfmode)
- return -EINVAL;
- if (!var->height)
- return -EINVAL;
- delta = 1 << fmode;
- lofsprite = shfsprite = (u_short *)spritememory;
- lspr = lofsprite + (delta << 1);
- if (par->bplcon0 & BPC0_LACE) {
- if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
- return -EINVAL;
- memset(lspr, 0, (var->height + 4) << fmode << 2);
- shfsprite += ((var->height + 5)&-2) << fmode;
- sspr = shfsprite + (delta << 1);
- } else {
- if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
- return -EINVAL;
- memset(lspr, 0, (var->height + 2) << fmode << 2);
- sspr = NULL;
- }
- for (height = (short)var->height - 1; height >= 0; height--) {
- bits = 16; words = delta; datawords = 0;
- for (width = (short)var->width - 1; width >= 0; width--) {
- unsigned long tdata = 0;
- /* FIXME: check the return value + test the change */
- get_user(tdata, data);
- data++;
-#ifdef __mc68000__
- asm volatile (
- "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
- "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
- : "=d" (datawords)
- : "0" (datawords), "d" (tdata));
-#else
- datawords = ((datawords << 1) & 0xfffefffe);
- datawords |= tdata & 1;
- datawords |= (tdata & 2) << (16 - 1);
-#endif
- if (--bits == 0) {
- bits = 16; --words;
-#ifdef __mc68000__
- asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
- : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
-#else
- *(lspr + delta) = (u_short) (datawords >> 16);
- *lspr++ = (u_short) (datawords & 0xffff);
-#endif
- }
- }
- if (bits < 16) {
- --words;
-#ifdef __mc68000__
- asm volatile (
- "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
- "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
- : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
-#else
- *(lspr + delta) = (u_short) (datawords >> (16 + bits));
- *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
-#endif
- }
- while (--words >= 0) {
-#ifdef __mc68000__
- asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
- : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
-#else
- *(lspr + delta) = 0;
- *lspr++ = 0;
-#endif
- }
-#ifdef __mc68000__
- asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
- : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
-#else
- lspr += delta;
- if (sspr) {
- u_short *tmp = lspr;
- lspr = sspr;
- sspr = tmp;
- }
-#endif
- }
- par->crsr.height = var->height;
- par->crsr.width = var->width;
- par->crsr.spot_x = var->xspot;
- par->crsr.spot_y = var->yspot;
- par->crsr.fmode = fmode;
- if (IS_AGA) {
- par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
- par->fmode |= sprfetchmode[fmode];
- custom.fmode = par->fmode;
- }
- return 0;
-}
-
-static int ami_get_cursorstate(struct fb_cursorstate *state,
- const struct amifb_par *par)
-{
- state->xoffset = par->crsr.crsr_x;
- state->yoffset = par->crsr.crsr_y;
- state->mode = cursormode;
- return 0;
-}
-
-static int ami_set_cursorstate(struct fb_cursorstate *state,
- struct amifb_par *par)
-{
- par->crsr.crsr_x = state->xoffset;
- par->crsr.crsr_y = state->yoffset;
- if ((cursormode = state->mode) == FB_CURSOR_OFF)
- cursorstate = -1;
- do_cursor = 1;
- return 0;
-}
-
-static void ami_set_sprite(const struct amifb_par *par)
-{
- copins *copl, *cops;
- u_short hs, vs, ve;
- u_long pl, ps;
- short mx, my;
-
- cops = copdisplay.list[currentcop][0];
- copl = copdisplay.list[currentcop][1];
- ps = pl = ZTWO_PADDR(dummysprite);
- mx = par->crsr.crsr_x - par->crsr.spot_x;
- my = par->crsr.crsr_y - par->crsr.spot_y;
- if (!(par->vmode & FB_VMODE_YWRAP)) {
- mx -= par->xoffset;
- my -= par->yoffset;
- }
- if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
- mx > -(short)par->crsr.width && mx < par->xres &&
- my > -(short)par->crsr.height && my < par->yres) {
- pl = ZTWO_PADDR(lofsprite);
- hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
- vs = par->diwstrt_v + (my << par->line_shift);
- ve = vs + (par->crsr.height << par->line_shift);
- if (par->bplcon0 & BPC0_LACE) {
- ps = ZTWO_PADDR(shfsprite);
- lofsprite[0] = spr2hw_pos(vs, hs);
- shfsprite[0] = spr2hw_pos(vs + 1, hs);
- if (mod2(vs)) {
- lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
- shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
- swap(pl, ps);
- } else {
- lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
- shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
- }
- } else {
- lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
- lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
- }
- }
- copl[cop_spr0ptrh].w[1] = highw(pl);
- copl[cop_spr0ptrl].w[1] = loww(pl);
- if (par->bplcon0 & BPC0_LACE) {
- cops[cop_spr0ptrh].w[1] = highw(ps);
- cops[cop_spr0ptrl].w[1] = loww(ps);
- }
-}
-
-
- /*
- * Initialise the Copper Initialisation List
- */
-
-static void __init ami_init_copper(void)
-{
- copins *cop = copdisplay.init;
- u_long p;
- int i;
-
- if (!IS_OCS) {
- (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
- (cop++)->l = CMOVE(0x0181, diwstrt);
- (cop++)->l = CMOVE(0x0281, diwstop);
- (cop++)->l = CMOVE(0x0000, diwhigh);
- } else
- (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
- p = ZTWO_PADDR(dummysprite);
- for (i = 0; i < 8; i++) {
- (cop++)->l = CMOVE(0, spr[i].pos);
- (cop++)->l = CMOVE(highw(p), sprpt[i]);
- (cop++)->l = CMOVE2(loww(p), sprpt[i]);
- }
-
- (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
- copdisplay.wait = cop;
- (cop++)->l = CEND;
- (cop++)->l = CMOVE(0, copjmp2);
- cop->l = CEND;
-
- custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
- custom.copjmp1 = 0;
-}
-
-static void ami_reinit_copper(const struct amifb_par *par)
-{
- copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
- copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
-}
-
-
- /*
- * Rebuild the Copper List
- *
- * We only change the things that are not static
- */
-
-static void ami_rebuild_copper(const struct amifb_par *par)
-{
- copins *copl, *cops;
- u_short line, h_end1, h_end2;
- short i;
- u_long p;
-
- if (IS_AGA && maxfmode + par->clk_shift == 0)
- h_end1 = par->diwstrt_h - 64;
- else
- h_end1 = par->htotal - 32;
- h_end2 = par->ddfstop + 64;
-
- ami_set_sprite(par);
-
- copl = copdisplay.rebuild[1];
- p = par->bplpt0;
- if (par->vmode & FB_VMODE_YWRAP) {
- if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
- if (par->yoffset > par->vyres - par->yres) {
- for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
- (copl++)->l = CMOVE(highw(p), bplpt[i]);
- (copl++)->l = CMOVE2(loww(p), bplpt[i]);
- }
- line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
- while (line >= 512) {
- (copl++)->l = CWAIT(h_end1, 510);
- line -= 512;
- }
- if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
- (copl++)->l = CWAIT(h_end1, line);
- else
- (copl++)->l = CWAIT(h_end2, line);
- p = par->bplpt0wrap;
- }
- } else
- p = par->bplpt0wrap;
- }
- for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
- (copl++)->l = CMOVE(highw(p), bplpt[i]);
- (copl++)->l = CMOVE2(loww(p), bplpt[i]);
- }
- copl->l = CEND;
-
- if (par->bplcon0 & BPC0_LACE) {
- cops = copdisplay.rebuild[0];
- p = par->bplpt0;
- if (mod2(par->diwstrt_v))
- p -= par->next_line;
- else
- p += par->next_line;
- if (par->vmode & FB_VMODE_YWRAP) {
- if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
- if (par->yoffset > par->vyres - par->yres + 1) {
- for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
- (cops++)->l = CMOVE(highw(p), bplpt[i]);
- (cops++)->l = CMOVE2(loww(p), bplpt[i]);
- }
- line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
- while (line >= 512) {
- (cops++)->l = CWAIT(h_end1, 510);
- line -= 512;
- }
- if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
- (cops++)->l = CWAIT(h_end1, line);
- else
- (cops++)->l = CWAIT(h_end2, line);
- p = par->bplpt0wrap;
- if (mod2(par->diwstrt_v + par->vyres -
- par->yoffset))
- p -= par->next_line;
- else
- p += par->next_line;
- }
- } else
- p = par->bplpt0wrap - par->next_line;
- }
- for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
- (cops++)->l = CMOVE(highw(p), bplpt[i]);
- (cops++)->l = CMOVE2(loww(p), bplpt[i]);
- }
- cops->l = CEND;
- }
-}
-
-
- /*
- * Build the Copper List
- */
-
-static void ami_build_copper(struct fb_info *info)
-{
- struct amifb_par *par = info->par;
- copins *copl, *cops;
- u_long p;
-
- currentcop = 1 - currentcop;
-
- copl = copdisplay.list[currentcop][1];
-
- (copl++)->l = CWAIT(0, 10);
- (copl++)->l = CMOVE(par->bplcon0, bplcon0);
- (copl++)->l = CMOVE(0, sprpt[0]);
- (copl++)->l = CMOVE2(0, sprpt[0]);
-
- if (par->bplcon0 & BPC0_LACE) {
- cops = copdisplay.list[currentcop][0];
-
- (cops++)->l = CWAIT(0, 10);
- (cops++)->l = CMOVE(par->bplcon0, bplcon0);
- (cops++)->l = CMOVE(0, sprpt[0]);
- (cops++)->l = CMOVE2(0, sprpt[0]);
-
- (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
- (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
- (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
- (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
- if (!IS_OCS) {
- (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
- par->diwstop_h, par->diwstop_v + 1), diwhigh);
- (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
- par->diwstop_h, par->diwstop_v), diwhigh);
-#if 0
- if (par->beamcon0 & BMC0_VARBEAMEN) {
- (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
- (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
- (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
- (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
- (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
- (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
- }
-#endif
- }
- p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
- (copl++)->l = CMOVE(highw(p), cop2lc);
- (copl++)->l = CMOVE2(loww(p), cop2lc);
- p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
- (cops++)->l = CMOVE(highw(p), cop2lc);
- (cops++)->l = CMOVE2(loww(p), cop2lc);
- copdisplay.rebuild[0] = cops;
- } else {
- (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
- (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
- if (!IS_OCS) {
- (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
- par->diwstop_h, par->diwstop_v), diwhigh);
-#if 0
- if (par->beamcon0 & BMC0_VARBEAMEN) {
- (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
- (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
- (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
- }
-#endif
- }
- }
- copdisplay.rebuild[1] = copl;
-
- ami_update_par(info);
- ami_rebuild_copper(info->par);
-}
-
-#ifndef MODULE
-static void __init amifb_setup_mcap(char *spec)
-{
- char *p;
- int vmin, vmax, hmin, hmax;
-
- /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
- * <V*> vertical freq. in Hz
- * <H*> horizontal freq. in kHz
- */
-
- if (!(p = strsep(&spec, ";")) || !*p)
- return;
- vmin = simple_strtoul(p, NULL, 10);
- if (vmin <= 0)
- return;
- if (!(p = strsep(&spec, ";")) || !*p)
- return;
- vmax = simple_strtoul(p, NULL, 10);
- if (vmax <= 0 || vmax <= vmin)
- return;
- if (!(p = strsep(&spec, ";")) || !*p)
- return;
- hmin = 1000 * simple_strtoul(p, NULL, 10);
- if (hmin <= 0)
- return;
- if (!(p = strsep(&spec, "")) || !*p)
- return;
- hmax = 1000 * simple_strtoul(p, NULL, 10);
- if (hmax <= 0 || hmax <= hmin)
- return;
-
- amifb_hfmin = hmin;
- amifb_hfmax = hmax;
- amifb_vfmin = vmin;
- amifb_vfmax = vmax;
-}
-
-static int __init amifb_setup(char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return 0;
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!*this_opt)
- continue;
- if (!strcmp(this_opt, "inverse")) {
- fb_invert_cmaps();
- } else if (!strcmp(this_opt, "ilbm"))
- amifb_ilbm = 1;
- else if (!strncmp(this_opt, "monitorcap:", 11))
- amifb_setup_mcap(this_opt + 11);
- else if (!strncmp(this_opt, "fstart:", 7))
- min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
- else
- mode_option = this_opt;
- }
-
- if (min_fstrt < 48)
- min_fstrt = 48;
-
- return 0;
-}
-#endif
-
-static int amifb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- int err;
- struct amifb_par par;
-
- /* Validate wanted screen parameters */
- err = ami_decode_var(var, &par, info);
- if (err)
- return err;
-
- /* Encode (possibly rounded) screen parameters */
- ami_encode_var(var, &par);
- return 0;
-}
-
-
-static int amifb_set_par(struct fb_info *info)
-{
- struct amifb_par *par = info->par;
- int error;
-
- do_vmode_pan = 0;
- do_vmode_full = 0;
-
- /* Decode wanted screen parameters */
- error = ami_decode_var(&info->var, par, info);
- if (error)
- return error;
-
- /* Set new videomode */
- ami_build_copper(info);
-
- /* Set VBlank trigger */
- do_vmode_full = 1;
-
- /* Update fix for new screen parameters */
- if (par->bpp == 1) {
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.type_aux = 0;
- } else if (amifb_ilbm) {
- info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
- info->fix.type_aux = par->next_line;
- } else {
- info->fix.type = FB_TYPE_PLANES;
- info->fix.type_aux = 0;
- }
- info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
-
- if (par->vmode & FB_VMODE_YWRAP) {
- info->fix.ywrapstep = 1;
- info->fix.xpanstep = 0;
- info->fix.ypanstep = 0;
- info->flags = FBINFO_HWACCEL_YWRAP |
- FBINFO_READS_FAST; /* override SCROLL_REDRAW */
- } else {
- info->fix.ywrapstep = 0;
- if (par->vmode & FB_VMODE_SMOOTH_XPAN)
- info->fix.xpanstep = 1;
- else
- info->fix.xpanstep = 16 << maxfmode;
- info->fix.ypanstep = 1;
- info->flags = FBINFO_HWACCEL_YPAN;
- }
- return 0;
-}
-
-
- /*
- * Set a single color register. The values supplied are already
- * rounded down to the hardware's capabilities (according to the
- * entries in the var structure). Return != 0 for invalid regno.
- */
-
-static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
-{
- const struct amifb_par *par = info->par;
-
- if (IS_AGA) {
- if (regno > 255)
- return 1;
- } else if (par->bplcon0 & BPC0_SHRES) {
- if (regno > 3)
- return 1;
- } else {
- if (regno > 31)
- return 1;
- }
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- if (!regno) {
- red0 = red;
- green0 = green;
- blue0 = blue;
- }
-
- /*
- * Update the corresponding Hardware Color Register, unless it's Color
- * Register 0 and the screen is blanked.
- *
- * VBlank is switched off to protect bplcon3 or ecs_palette[] from
- * being changed by ami_do_blank() during the VBlank.
- */
-
- if (regno || !is_blanked) {
-#if defined(CONFIG_FB_AMIGA_AGA)
- if (IS_AGA) {
- u_short bplcon3 = par->bplcon3;
- VBlankOff();
- custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
- custom.color[regno & 31] = rgb2hw8_high(red, green,
- blue);
- custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
- BPC3_LOCT;
- custom.color[regno & 31] = rgb2hw8_low(red, green,
- blue);
- custom.bplcon3 = bplcon3;
- VBlankOn();
- } else
-#endif
-#if defined(CONFIG_FB_AMIGA_ECS)
- if (par->bplcon0 & BPC0_SHRES) {
- u_short color, mask;
- int i;
-
- mask = 0x3333;
- color = rgb2hw2(red, green, blue);
- VBlankOff();
- for (i = regno + 12; i >= (int)regno; i -= 4)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- mask <<= 2; color >>= 2;
- regno = down16(regno) + mul4(mod4(regno));
- for (i = regno + 3; i >= (int)regno; i--)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- VBlankOn();
- } else
-#endif
- custom.color[regno] = rgb2hw4(red, green, blue);
- }
- return 0;
-}
-
-
- /*
- * Blank the display.
- */
-
-static int amifb_blank(int blank, struct fb_info *info)
-{
- do_blank = blank ? blank : -1;
-
- return 0;
-}
-
-
- /*
- * Pan or Wrap the Display
- *
- * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- */
-
-static int amifb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- if (!(var->vmode & FB_VMODE_YWRAP)) {
- /*
- * TODO: There will be problems when xpan!=1, so some columns
- * on the right side will never be seen
- */
- if (var->xoffset + info->var.xres >
- upx(16 << maxfmode, info->var.xres_virtual))
- return -EINVAL;
- }
- ami_pan_var(var, info);
- return 0;
-}
-
-
-#if BITS_PER_LONG == 32
-#define BYTES_PER_LONG 4
-#define SHIFT_PER_LONG 5
-#elif BITS_PER_LONG == 64
-#define BYTES_PER_LONG 8
-#define SHIFT_PER_LONG 6
-#else
-#define Please update me
-#endif
-
-
- /*
- * Compose two values, using a bitmask as decision value
- * This is equivalent to (a & mask) | (b & ~mask)
- */
-
-static inline unsigned long comp(unsigned long a, unsigned long b,
- unsigned long mask)
-{
- return ((a ^ b) & mask) ^ b;
-}
-
-
-static inline unsigned long xor(unsigned long a, unsigned long b,
- unsigned long mask)
-{
- return (a & mask) ^ b;
-}
-
-
- /*
- * Unaligned forward bit copy using 32-bit or 64-bit memory accesses
- */
-
-static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
- int src_idx, u32 n)
-{
- unsigned long first, last;
- int shift = dst_idx - src_idx, left, right;
- unsigned long d0, d1;
- int m;
-
- if (!n)
- return;
-
- shift = dst_idx - src_idx;
- first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
-
- if (!shift) {
- // Same alignment for source and dest
-
- if (dst_idx + n <= BITS_PER_LONG) {
- // Single word
- if (last)
- first &= last;
- *dst = comp(*src, *dst, first);
- } else {
- // Multiple destination words
- // Leading bits
- if (first) {
- *dst = comp(*src, *dst, first);
- dst++;
- src++;
- n -= BITS_PER_LONG - dst_idx;
- }
-
- // Main chunk
- n /= BITS_PER_LONG;
- while (n >= 8) {
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
- n -= 8;
- }
- while (n--)
- *dst++ = *src++;
-
- // Trailing bits
- if (last)
- *dst = comp(*src, *dst, last);
- }
- } else {
- // Different alignment for source and dest
-
- right = shift & (BITS_PER_LONG - 1);
- left = -shift & (BITS_PER_LONG - 1);
-
- if (dst_idx + n <= BITS_PER_LONG) {
- // Single destination word
- if (last)
- first &= last;
- if (shift > 0) {
- // Single source word
- *dst = comp(*src >> right, *dst, first);
- } else if (src_idx + n <= BITS_PER_LONG) {
- // Single source word
- *dst = comp(*src << left, *dst, first);
- } else {
- // 2 source words
- d0 = *src++;
- d1 = *src;
- *dst = comp(d0 << left | d1 >> right, *dst,
- first);
- }
- } else {
- // Multiple destination words
- d0 = *src++;
- // Leading bits
- if (shift > 0) {
- // Single source word
- *dst = comp(d0 >> right, *dst, first);
- dst++;
- n -= BITS_PER_LONG - dst_idx;
- } else {
- // 2 source words
- d1 = *src++;
- *dst = comp(d0 << left | d1 >> right, *dst,
- first);
- d0 = d1;
- dst++;
- n -= BITS_PER_LONG - dst_idx;
- }
-
- // Main chunk
- m = n % BITS_PER_LONG;
- n /= BITS_PER_LONG;
- while (n >= 4) {
- d1 = *src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- d1 = *src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- d1 = *src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- d1 = *src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- n -= 4;
- }
- while (n--) {
- d1 = *src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- }
-
- // Trailing bits
- if (last) {
- if (m <= right) {
- // Single source word
- *dst = comp(d0 << left, *dst, last);
- } else {
- // 2 source words
- d1 = *src;
- *dst = comp(d0 << left | d1 >> right,
- *dst, last);
- }
- }
- }
- }
-}
-
-
- /*
- * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
- */
-
-static void bitcpy_rev(unsigned long *dst, int dst_idx,
- const unsigned long *src, int src_idx, u32 n)
-{
- unsigned long first, last;
- int shift = dst_idx - src_idx, left, right;
- unsigned long d0, d1;
- int m;
-
- if (!n)
- return;
-
- dst += (n - 1) / BITS_PER_LONG;
- src += (n - 1) / BITS_PER_LONG;
- if ((n - 1) % BITS_PER_LONG) {
- dst_idx += (n - 1) % BITS_PER_LONG;
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= BITS_PER_LONG - 1;
- src_idx += (n - 1) % BITS_PER_LONG;
- src += src_idx >> SHIFT_PER_LONG;
- src_idx &= BITS_PER_LONG - 1;
- }
-
- shift = dst_idx - src_idx;
- first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
- last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
-
- if (!shift) {
- // Same alignment for source and dest
-
- if ((unsigned long)dst_idx + 1 >= n) {
- // Single word
- if (last)
- first &= last;
- *dst = comp(*src, *dst, first);
- } else {
- // Multiple destination words
- // Leading bits
- if (first) {
- *dst = comp(*src, *dst, first);
- dst--;
- src--;
- n -= dst_idx + 1;
- }
-
- // Main chunk
- n /= BITS_PER_LONG;
- while (n >= 8) {
- *dst-- = *src--;
- *dst-- = *src--;
- *dst-- = *src--;
- *dst-- = *src--;
- *dst-- = *src--;
- *dst-- = *src--;
- *dst-- = *src--;
- *dst-- = *src--;
- n -= 8;
- }
- while (n--)
- *dst-- = *src--;
-
- // Trailing bits
- if (last)
- *dst = comp(*src, *dst, last);
- }
- } else {
- // Different alignment for source and dest
-
- right = shift & (BITS_PER_LONG - 1);
- left = -shift & (BITS_PER_LONG - 1);
-
- if ((unsigned long)dst_idx + 1 >= n) {
- // Single destination word
- if (last)
- first &= last;
- if (shift < 0) {
- // Single source word
- *dst = comp(*src << left, *dst, first);
- } else if (1 + (unsigned long)src_idx >= n) {
- // Single source word
- *dst = comp(*src >> right, *dst, first);
- } else {
- // 2 source words
- d0 = *src--;
- d1 = *src;
- *dst = comp(d0 >> right | d1 << left, *dst,
- first);
- }
- } else {
- // Multiple destination words
- d0 = *src--;
- // Leading bits
- if (shift < 0) {
- // Single source word
- *dst = comp(d0 << left, *dst, first);
- dst--;
- n -= dst_idx + 1;
- } else {
- // 2 source words
- d1 = *src--;
- *dst = comp(d0 >> right | d1 << left, *dst,
- first);
- d0 = d1;
- dst--;
- n -= dst_idx + 1;
- }
-
- // Main chunk
- m = n % BITS_PER_LONG;
- n /= BITS_PER_LONG;
- while (n >= 4) {
- d1 = *src--;
- *dst-- = d0 >> right | d1 << left;
- d0 = d1;
- d1 = *src--;
- *dst-- = d0 >> right | d1 << left;
- d0 = d1;
- d1 = *src--;
- *dst-- = d0 >> right | d1 << left;
- d0 = d1;
- d1 = *src--;
- *dst-- = d0 >> right | d1 << left;
- d0 = d1;
- n -= 4;
- }
- while (n--) {
- d1 = *src--;
- *dst-- = d0 >> right | d1 << left;
- d0 = d1;
- }
-
- // Trailing bits
- if (last) {
- if (m <= left) {
- // Single source word
- *dst = comp(d0 >> right, *dst, last);
- } else {
- // 2 source words
- d1 = *src;
- *dst = comp(d0 >> right | d1 << left,
- *dst, last);
- }
- }
- }
- }
-}
-
-
- /*
- * Unaligned forward inverting bit copy using 32-bit or 64-bit memory
- * accesses
- */
-
-static void bitcpy_not(unsigned long *dst, int dst_idx,
- const unsigned long *src, int src_idx, u32 n)
-{
- unsigned long first, last;
- int shift = dst_idx - src_idx, left, right;
- unsigned long d0, d1;
- int m;
-
- if (!n)
- return;
-
- shift = dst_idx - src_idx;
- first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
-
- if (!shift) {
- // Same alignment for source and dest
-
- if (dst_idx + n <= BITS_PER_LONG) {
- // Single word
- if (last)
- first &= last;
- *dst = comp(~*src, *dst, first);
- } else {
- // Multiple destination words
- // Leading bits
- if (first) {
- *dst = comp(~*src, *dst, first);
- dst++;
- src++;
- n -= BITS_PER_LONG - dst_idx;
- }
-
- // Main chunk
- n /= BITS_PER_LONG;
- while (n >= 8) {
- *dst++ = ~*src++;
- *dst++ = ~*src++;
- *dst++ = ~*src++;
- *dst++ = ~*src++;
- *dst++ = ~*src++;
- *dst++ = ~*src++;
- *dst++ = ~*src++;
- *dst++ = ~*src++;
- n -= 8;
- }
- while (n--)
- *dst++ = ~*src++;
-
- // Trailing bits
- if (last)
- *dst = comp(~*src, *dst, last);
- }
- } else {
- // Different alignment for source and dest
-
- right = shift & (BITS_PER_LONG - 1);
- left = -shift & (BITS_PER_LONG - 1);
-
- if (dst_idx + n <= BITS_PER_LONG) {
- // Single destination word
- if (last)
- first &= last;
- if (shift > 0) {
- // Single source word
- *dst = comp(~*src >> right, *dst, first);
- } else if (src_idx + n <= BITS_PER_LONG) {
- // Single source word
- *dst = comp(~*src << left, *dst, first);
- } else {
- // 2 source words
- d0 = ~*src++;
- d1 = ~*src;
- *dst = comp(d0 << left | d1 >> right, *dst,
- first);
- }
- } else {
- // Multiple destination words
- d0 = ~*src++;
- // Leading bits
- if (shift > 0) {
- // Single source word
- *dst = comp(d0 >> right, *dst, first);
- dst++;
- n -= BITS_PER_LONG - dst_idx;
- } else {
- // 2 source words
- d1 = ~*src++;
- *dst = comp(d0 << left | d1 >> right, *dst,
- first);
- d0 = d1;
- dst++;
- n -= BITS_PER_LONG - dst_idx;
- }
-
- // Main chunk
- m = n % BITS_PER_LONG;
- n /= BITS_PER_LONG;
- while (n >= 4) {
- d1 = ~*src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- d1 = ~*src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- d1 = ~*src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- d1 = ~*src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- n -= 4;
- }
- while (n--) {
- d1 = ~*src++;
- *dst++ = d0 << left | d1 >> right;
- d0 = d1;
- }
-
- // Trailing bits
- if (last) {
- if (m <= right) {
- // Single source word
- *dst = comp(d0 << left, *dst, last);
- } else {
- // 2 source words
- d1 = ~*src;
- *dst = comp(d0 << left | d1 >> right,
- *dst, last);
- }
- }
- }
- }
-}
-
-
- /*
- * Unaligned 32-bit pattern fill using 32/64-bit memory accesses
- */
-
-static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
-{
- unsigned long val = pat;
- unsigned long first, last;
-
- if (!n)
- return;
-
-#if BITS_PER_LONG == 64
- val |= val << 32;
-#endif
-
- first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
-
- if (dst_idx + n <= BITS_PER_LONG) {
- // Single word
- if (last)
- first &= last;
- *dst = comp(val, *dst, first);
- } else {
- // Multiple destination words
- // Leading bits
- if (first) {
- *dst = comp(val, *dst, first);
- dst++;
- n -= BITS_PER_LONG - dst_idx;
- }
-
- // Main chunk
- n /= BITS_PER_LONG;
- while (n >= 8) {
- *dst++ = val;
- *dst++ = val;
- *dst++ = val;
- *dst++ = val;
- *dst++ = val;
- *dst++ = val;
- *dst++ = val;
- *dst++ = val;
- n -= 8;
- }
- while (n--)
- *dst++ = val;
-
- // Trailing bits
- if (last)
- *dst = comp(val, *dst, last);
- }
-}
-
-
- /*
- * Unaligned 32-bit pattern xor using 32/64-bit memory accesses
- */
-
-static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
-{
- unsigned long val = pat;
- unsigned long first, last;
-
- if (!n)
- return;
-
-#if BITS_PER_LONG == 64
- val |= val << 32;
-#endif
-
- first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
-
- if (dst_idx + n <= BITS_PER_LONG) {
- // Single word
- if (last)
- first &= last;
- *dst = xor(val, *dst, first);
- } else {
- // Multiple destination words
- // Leading bits
- if (first) {
- *dst = xor(val, *dst, first);
- dst++;
- n -= BITS_PER_LONG - dst_idx;
- }
-
- // Main chunk
- n /= BITS_PER_LONG;
- while (n >= 4) {
- *dst++ ^= val;
- *dst++ ^= val;
- *dst++ ^= val;
- *dst++ ^= val;
- n -= 4;
- }
- while (n--)
- *dst++ ^= val;
-
- // Trailing bits
- if (last)
- *dst = xor(val, *dst, last);
- }
-}
-
-static inline void fill_one_line(int bpp, unsigned long next_plane,
- unsigned long *dst, int dst_idx, u32 n,
- u32 color)
-{
- while (1) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG - 1);
- bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
- if (!--bpp)
- break;
- color >>= 1;
- dst_idx += next_plane * 8;
- }
-}
-
-static inline void xor_one_line(int bpp, unsigned long next_plane,
- unsigned long *dst, int dst_idx, u32 n,
- u32 color)
-{
- while (color) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG - 1);
- bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
- if (!--bpp)
- break;
- color >>= 1;
- dst_idx += next_plane * 8;
- }
-}
-
-
-static void amifb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
-{
- struct amifb_par *par = info->par;
- int dst_idx, x2, y2;
- unsigned long *dst;
- u32 width, height;
-
- if (!rect->width || !rect->height)
- return;
-
- /*
- * We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly.
- * */
- x2 = rect->dx + rect->width;
- y2 = rect->dy + rect->height;
- x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
- y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
- width = x2 - rect->dx;
- height = y2 - rect->dy;
-
- dst = (unsigned long *)
- ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
- dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
- dst_idx += rect->dy * par->next_line * 8 + rect->dx;
- while (height--) {
- switch (rect->rop) {
- case ROP_COPY:
- fill_one_line(info->var.bits_per_pixel,
- par->next_plane, dst, dst_idx, width,
- rect->color);
- break;
-
- case ROP_XOR:
- xor_one_line(info->var.bits_per_pixel, par->next_plane,
- dst, dst_idx, width, rect->color);
- break;
- }
- dst_idx += par->next_line * 8;
- }
-}
-
-static inline void copy_one_line(int bpp, unsigned long next_plane,
- unsigned long *dst, int dst_idx,
- unsigned long *src, int src_idx, u32 n)
-{
- while (1) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG - 1);
- src += src_idx >> SHIFT_PER_LONG;
- src_idx &= (BITS_PER_LONG - 1);
- bitcpy(dst, dst_idx, src, src_idx, n);
- if (!--bpp)
- break;
- dst_idx += next_plane * 8;
- src_idx += next_plane * 8;
- }
-}
-
-static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
- unsigned long *dst, int dst_idx,
- unsigned long *src, int src_idx, u32 n)
-{
- while (1) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG - 1);
- src += src_idx >> SHIFT_PER_LONG;
- src_idx &= (BITS_PER_LONG - 1);
- bitcpy_rev(dst, dst_idx, src, src_idx, n);
- if (!--bpp)
- break;
- dst_idx += next_plane * 8;
- src_idx += next_plane * 8;
- }
-}
-
-
-static void amifb_copyarea(struct fb_info *info,
- const struct fb_copyarea *area)
-{
- struct amifb_par *par = info->par;
- int x2, y2;
- u32 dx, dy, sx, sy, width, height;
- unsigned long *dst, *src;
- int dst_idx, src_idx;
- int rev_copy = 0;
-
- /* clip the destination */
- x2 = area->dx + area->width;
- y2 = area->dy + area->height;
- dx = area->dx > 0 ? area->dx : 0;
- dy = area->dy > 0 ? area->dy : 0;
- x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
- y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
- width = x2 - dx;
- height = y2 - dy;
-
- if (area->sx + dx < area->dx || area->sy + dy < area->dy)
- return;
-
- /* update sx,sy */
- sx = area->sx + (dx - area->dx);
- sy = area->sy + (dy - area->dy);
-
- /* the source must be completely inside the virtual screen */
- if (sx + width > info->var.xres_virtual ||
- sy + height > info->var.yres_virtual)
- return;
-
- if (dy > sy || (dy == sy && dx > sx)) {
- dy += height;
- sy += height;
- rev_copy = 1;
- }
- dst = (unsigned long *)
- ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
- src = dst;
- dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
- src_idx = dst_idx;
- dst_idx += dy * par->next_line * 8 + dx;
- src_idx += sy * par->next_line * 8 + sx;
- if (rev_copy) {
- while (height--) {
- dst_idx -= par->next_line * 8;
- src_idx -= par->next_line * 8;
- copy_one_line_rev(info->var.bits_per_pixel,
- par->next_plane, dst, dst_idx, src,
- src_idx, width);
- }
- } else {
- while (height--) {
- copy_one_line(info->var.bits_per_pixel,
- par->next_plane, dst, dst_idx, src,
- src_idx, width);
- dst_idx += par->next_line * 8;
- src_idx += par->next_line * 8;
- }
- }
-}
-
-
-static inline void expand_one_line(int bpp, unsigned long next_plane,
- unsigned long *dst, int dst_idx, u32 n,
- const u8 *data, u32 bgcolor, u32 fgcolor)
-{
- const unsigned long *src;
- int src_idx;
-
- while (1) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG - 1);
- if ((bgcolor ^ fgcolor) & 1) {
- src = (unsigned long *)
- ((unsigned long)data & ~(BYTES_PER_LONG - 1));
- src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
- if (fgcolor & 1)
- bitcpy(dst, dst_idx, src, src_idx, n);
- else
- bitcpy_not(dst, dst_idx, src, src_idx, n);
- /* set or clear */
- } else
- bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
- if (!--bpp)
- break;
- bgcolor >>= 1;
- fgcolor >>= 1;
- dst_idx += next_plane * 8;
- }
-}
-
-
-static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- struct amifb_par *par = info->par;
- int x2, y2;
- unsigned long *dst;
- int dst_idx;
- const char *src;
- u32 dx, dy, width, height, pitch;
-
- /*
- * We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly like we are
- * doing here.
- */
- x2 = image->dx + image->width;
- y2 = image->dy + image->height;
- dx = image->dx;
- dy = image->dy;
- x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
- y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
- width = x2 - dx;
- height = y2 - dy;
-
- if (image->depth == 1) {
- dst = (unsigned long *)
- ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
- dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
- dst_idx += dy * par->next_line * 8 + dx;
- src = image->data;
- pitch = (image->width + 7) / 8;
- while (height--) {
- expand_one_line(info->var.bits_per_pixel,
- par->next_plane, dst, dst_idx, width,
- src, image->bg_color,
- image->fg_color);
- dst_idx += par->next_line * 8;
- src += pitch;
- }
- } else {
- c2p_planar(info->screen_base, image->data, dx, dy, width,
- height, par->next_line, par->next_plane,
- image->width, info->var.bits_per_pixel);
- }
-}
-
-
- /*
- * Amiga Frame Buffer Specific ioctls
- */
-
-static int amifb_ioctl(struct fb_info *info,
- unsigned int cmd, unsigned long arg)
-{
- union {
- struct fb_fix_cursorinfo fix;
- struct fb_var_cursorinfo var;
- struct fb_cursorstate state;
- } crsr;
- void __user *argp = (void __user *)arg;
- int i;
-
- switch (cmd) {
- case FBIOGET_FCURSORINFO:
- i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
- if (i)
- return i;
- return copy_to_user(argp, &crsr.fix,
- sizeof(crsr.fix)) ? -EFAULT : 0;
-
- case FBIOGET_VCURSORINFO:
- i = ami_get_var_cursorinfo(&crsr.var,
- ((struct fb_var_cursorinfo __user *)arg)->data,
- info->par);
- if (i)
- return i;
- return copy_to_user(argp, &crsr.var,
- sizeof(crsr.var)) ? -EFAULT : 0;
-
- case FBIOPUT_VCURSORINFO:
- if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
- return -EFAULT;
- return ami_set_var_cursorinfo(&crsr.var,
- ((struct fb_var_cursorinfo __user *)arg)->data,
- info->par);
-
- case FBIOGET_CURSORSTATE:
- i = ami_get_cursorstate(&crsr.state, info->par);
- if (i)
- return i;
- return copy_to_user(argp, &crsr.state,
- sizeof(crsr.state)) ? -EFAULT : 0;
-
- case FBIOPUT_CURSORSTATE:
- if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
- return -EFAULT;
- return ami_set_cursorstate(&crsr.state, info->par);
- }
- return -EINVAL;
-}
-
-
- /*
- * Flash the cursor (called by VBlank interrupt)
- */
-
-static int flash_cursor(void)
-{
- static int cursorcount = 1;
-
- if (cursormode == FB_CURSOR_FLASH) {
- if (!--cursorcount) {
- cursorstate = -cursorstate;
- cursorcount = cursorrate;
- if (!is_blanked)
- return 1;
- }
- }
- return 0;
-}
-
- /*
- * VBlank Display Interrupt
- */
-
-static irqreturn_t amifb_interrupt(int irq, void *dev_id)
-{
- struct amifb_par *par = dev_id;
-
- if (do_vmode_pan || do_vmode_full)
- ami_update_display(par);
-
- if (do_vmode_full)
- ami_init_display(par);
-
- if (do_vmode_pan) {
- flash_cursor();
- ami_rebuild_copper(par);
- do_cursor = do_vmode_pan = 0;
- } else if (do_cursor) {
- flash_cursor();
- ami_set_sprite(par);
- do_cursor = 0;
- } else {
- if (flash_cursor())
- ami_set_sprite(par);
- }
-
- if (do_blank) {
- ami_do_blank(par);
- do_blank = 0;
- }
-
- if (do_vmode_full) {
- ami_reinit_copper(par);
- do_vmode_full = 0;
- }
- return IRQ_HANDLED;
-}
-
-
-static const struct fb_ops amifb_ops = {
- .owner = THIS_MODULE,
- __FB_DEFAULT_IOMEM_OPS_RDWR,
- .fb_check_var = amifb_check_var,
- .fb_set_par = amifb_set_par,
- .fb_setcolreg = amifb_setcolreg,
- .fb_blank = amifb_blank,
- .fb_pan_display = amifb_pan_display,
- .fb_fillrect = amifb_fillrect,
- .fb_copyarea = amifb_copyarea,
- .fb_imageblit = amifb_imageblit,
- .fb_ioctl = amifb_ioctl,
- __FB_DEFAULT_IOMEM_OPS_MMAP,
-};
-
-
- /*
- * Allocate, Clear and Align a Block of Chip Memory
- */
-
-static void *aligned_chipptr;
-
-static inline u_long __init chipalloc(u_long size)
-{
- aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
- if (!aligned_chipptr) {
- pr_err("amifb: No Chip RAM for frame buffer");
- return 0;
- }
- memset(aligned_chipptr, 0, size);
- return (u_long)aligned_chipptr;
-}
-
-static inline void chipfree(void)
-{
- if (aligned_chipptr)
- amiga_chip_free(aligned_chipptr);
-}
-
-
- /*
- * Initialisation
- */
-
-static int __init amifb_probe(struct platform_device *pdev)
-{
- struct fb_info *info;
- int tag, i, err = 0;
- u_long chipptr;
- u_int defmode;
-
-#ifndef MODULE
- char *option = NULL;
-
- if (fb_get_options("amifb", &option)) {
- amifb_video_off();
- return -ENODEV;
- }
- amifb_setup(option);
-#endif
- custom.dmacon = DMAF_ALL | DMAF_MASTER;
-
- info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
- if (!info)
- return -ENOMEM;
-
- strcpy(info->fix.id, "Amiga ");
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- info->fix.accel = FB_ACCEL_AMIGABLITT;
-
- switch (amiga_chipset) {
-#ifdef CONFIG_FB_AMIGA_OCS
- case CS_OCS:
- strcat(info->fix.id, "OCS");
-default_chipset:
- chipset = TAG_OCS;
- maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
- maxdepth[TAG_HIRES] = 4;
- maxdepth[TAG_LORES] = 6;
- maxfmode = TAG_FMODE_1;
- defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
- info->fix.smem_len = VIDEOMEMSIZE_OCS;
- break;
-#endif /* CONFIG_FB_AMIGA_OCS */
-
-#ifdef CONFIG_FB_AMIGA_ECS
- case CS_ECS:
- strcat(info->fix.id, "ECS");
- chipset = TAG_ECS;
- maxdepth[TAG_SHRES] = 2;
- maxdepth[TAG_HIRES] = 4;
- maxdepth[TAG_LORES] = 6;
- maxfmode = TAG_FMODE_1;
- if (AMIGAHW_PRESENT(AMBER_FF))
- defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
- : DEFMODE_AMBER_NTSC;
- else
- defmode = amiga_vblank == 50 ? DEFMODE_PAL
- : DEFMODE_NTSC;
- if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
- VIDEOMEMSIZE_ECS_2M)
- info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
- else
- info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
- break;
-#endif /* CONFIG_FB_AMIGA_ECS */
-
-#ifdef CONFIG_FB_AMIGA_AGA
- case CS_AGA:
- strcat(info->fix.id, "AGA");
- chipset = TAG_AGA;
- maxdepth[TAG_SHRES] = 8;
- maxdepth[TAG_HIRES] = 8;
- maxdepth[TAG_LORES] = 8;
- maxfmode = TAG_FMODE_4;
- defmode = DEFMODE_AGA;
- if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
- VIDEOMEMSIZE_AGA_2M)
- info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
- else
- info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
- break;
-#endif /* CONFIG_FB_AMIGA_AGA */
-
- default:
-#ifdef CONFIG_FB_AMIGA_OCS
- printk("Unknown graphics chipset, defaulting to OCS\n");
- strcat(info->fix.id, "Unknown");
- goto default_chipset;
-#else /* CONFIG_FB_AMIGA_OCS */
- err = -ENODEV;
- goto release;
-#endif /* CONFIG_FB_AMIGA_OCS */
- break;
- }
-
- /*
- * Calculate the Pixel Clock Values for this Machine
- */
-
- {
- u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
-
- pixclock[TAG_SHRES] = (tmp + 4) / 8; /* SHRES: 35 ns / 28 MHz */
- pixclock[TAG_HIRES] = (tmp + 2) / 4; /* HIRES: 70 ns / 14 MHz */
- pixclock[TAG_LORES] = (tmp + 1) / 2; /* LORES: 140 ns / 7 MHz */
- }
-
- /*
- * Replace the Tag Values with the Real Pixel Clock Values
- */
-
- for (i = 0; i < NUM_TOTAL_MODES; i++) {
- struct fb_videomode *mode = &ami_modedb[i];
- tag = mode->pixclock;
- if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
- mode->pixclock = pixclock[tag];
- }
- }
-
- if (amifb_hfmin) {
- info->monspecs.hfmin = amifb_hfmin;
- info->monspecs.hfmax = amifb_hfmax;
- info->monspecs.vfmin = amifb_vfmin;
- info->monspecs.vfmax = amifb_vfmax;
- } else {
- /*
- * These are for a typical Amiga monitor (e.g. A1960)
- */
- info->monspecs.hfmin = 15000;
- info->monspecs.hfmax = 38000;
- info->monspecs.vfmin = 49;
- info->monspecs.vfmax = 90;
- }
-
- info->fbops = &amifb_ops;
- info->device = &pdev->dev;
-
- if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
- NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
- err = -EINVAL;
- goto release;
- }
-
- fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
- &info->modelist);
-
- round_down_bpp = 0;
- chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
- DUMMYSPRITEMEMSIZE + COPINITSIZE +
- 4 * COPLISTSIZE);
- if (!chipptr) {
- err = -ENOMEM;
- goto release;
- }
-
- assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
- assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
- assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
- assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
- assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
- assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
- assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
- assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
-
- /*
- * access the videomem with writethrough cache
- */
- info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
- videomemory = (u_long)ioremap_wt(info->fix.smem_start,
- info->fix.smem_len);
- if (!videomemory) {
- dev_warn(&pdev->dev,
- "Unable to map videomem cached writethrough\n");
- info->screen_base = ZTWO_VADDR(info->fix.smem_start);
- } else
- info->screen_base = (char *)videomemory;
-
- memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
-
- /*
- * Make sure the Copper has something to do
- */
- ami_init_copper();
-
- /*
- * Enable Display DMA
- */
- custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
- DMAF_BLITTER | DMAF_SPRITE;
-
- err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
- "fb vertb handler", info->par);
- if (err)
- goto disable_dma;
-
- err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
- if (err)
- goto free_irq;
-
- platform_set_drvdata(pdev, info);
-
- err = register_framebuffer(info);
- if (err)
- goto unset_drvdata;
-
- fb_info(info, "%s frame buffer device, using %dK of video memory\n",
- info->fix.id, info->fix.smem_len>>10);
-
- return 0;
-
-unset_drvdata:
- fb_dealloc_cmap(&info->cmap);
-free_irq:
- free_irq(IRQ_AMIGA_COPPER, info->par);
-disable_dma:
- custom.dmacon = DMAF_ALL | DMAF_MASTER;
- if (videomemory)
- iounmap((void *)videomemory);
- chipfree();
-release:
- framebuffer_release(info);
- return err;
-}
-
-
-static void __exit amifb_remove(struct platform_device *pdev)
-{
- struct fb_info *info = platform_get_drvdata(pdev);
-
- unregister_framebuffer(info);
- fb_dealloc_cmap(&info->cmap);
- free_irq(IRQ_AMIGA_COPPER, info->par);
- custom.dmacon = DMAF_ALL | DMAF_MASTER;
- if (videomemory)
- iounmap((void *)videomemory);
- chipfree();
- framebuffer_release(info);
- amifb_video_off();
-}
-
-/*
- * amifb_remove() lives in .exit.text. For drivers registered via
- * module_platform_driver_probe() this ok because they cannot get unboud at
- * runtime. The driver needs to be marked with __refdata, otherwise modpost
- * triggers a section mismatch warning.
- */
-static struct platform_driver amifb_driver __refdata = {
- .remove = __exit_p(amifb_remove),
- .driver = {
- .name = "amiga-video",
- },
-};
-
-module_platform_driver_probe(amifb_driver, amifb_probe);
-
-MODULE_DESCRIPTION("Amiga builtin chipset frame buffer driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:amiga-video");
diff --git a/drivers/video/fbdev/atafb.c b/drivers/video/fbdev/atafb.c
deleted file mode 100644
index b8ed1c537..000000000
--- a/drivers/video/fbdev/atafb.c
+++ /dev/null
@@ -1,3188 +0,0 @@
-/*
- * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
- *
- * Copyright (C) 1994 Martin Schaller & Roman Hodek
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- * History:
- * - 03 Jan 95: Original version by Martin Schaller: The TT driver and
- * all the device independent stuff
- * - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
- * and wrote the Falcon, ST(E), and External drivers
- * based on the original TT driver.
- * - 07 May 95: Martin: Added colormap operations for the external driver
- * - 21 May 95: Martin: Added support for overscan
- * Andreas: some bug fixes for this
- * - Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
- * Programmable Falcon video modes
- * (thanks to Christian Cartus for documentation
- * of VIDEL registers).
- * - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
- * on minor 24...31. "user0" may be set on commandline by
- * "R<x>;<y>;<depth>". (Makes sense only on Falcon)
- * Video mode switch on Falcon now done at next VBL interrupt
- * to avoid the annoying right shift of the screen.
- * - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
- * The external-part is legacy, therefore hardware-specific
- * functions like panning/hardwarescrolling/blanking isn't
- * supported.
- * - 29 Sep 97: Juergen: added Romans suggestion for pan_display
- * (var->xoffset was changed even if no set_screen_base avail.)
- * - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
- * we know how to set the colors
- * ext_*palette: read from ext_colors (former MV300_colors)
- * write to ext_colors and RAMDAC
- *
- * To do:
- * - For the Falcon it is not possible to set random video modes on
- * SM124 and SC/TV, only the bootup resolution is supported.
- *
- */
-
-#define ATAFB_TT
-#define ATAFB_STE
-#define ATAFB_EXT
-#define ATAFB_FALCON
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <asm/setup.h>
-#include <linux/uaccess.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_stram.h>
-
-#include <linux/fb.h>
-#include <asm/atarikb.h>
-
-#include "c2p.h"
-#include "atafb.h"
-
-#define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
-#define SWITCH_SND6 0x40
-#define SWITCH_SND7 0x80
-#define SWITCH_NONE 0x00
-
-
-static int default_par; /* default resolution (0=none) */
-
-static unsigned long default_mem_req;
-
-static int hwscroll = -1;
-
-static int use_hwscroll = 1;
-
-static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
-static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
-static int ovsc_offset, ovsc_addlen;
-
- /*
- * Hardware parameters for current mode
- */
-
-static struct atafb_par {
- void *screen_base;
- int yres_virtual;
- u_long next_line;
-#if defined ATAFB_TT || defined ATAFB_STE
- union {
- struct {
- int mode;
- int sync;
- } tt, st;
-#endif
-#ifdef ATAFB_FALCON
- struct falcon_hw {
- /* Here are fields for storing a video mode, as direct
- * parameters for the hardware.
- */
- short sync;
- short line_width;
- short line_offset;
- short st_shift;
- short f_shift;
- short vid_control;
- short vid_mode;
- short xoffset;
- short hht, hbb, hbe, hdb, hde, hss;
- short vft, vbb, vbe, vdb, vde, vss;
- /* auxiliary information */
- short mono;
- short ste_mode;
- short bpp;
- u32 pseudo_palette[16];
- } falcon;
-#endif
- /* Nothing needed for external mode */
- } hw;
-} current_par;
-
-/* Don't calculate an own resolution, and thus don't change the one found when
- * booting (currently used for the Falcon to keep settings for internal video
- * hardware extensions (e.g. ScreenBlaster) */
-static int DontCalcRes = 0;
-
-#ifdef ATAFB_FALCON
-#define HHT hw.falcon.hht
-#define HBB hw.falcon.hbb
-#define HBE hw.falcon.hbe
-#define HDB hw.falcon.hdb
-#define HDE hw.falcon.hde
-#define HSS hw.falcon.hss
-#define VFT hw.falcon.vft
-#define VBB hw.falcon.vbb
-#define VBE hw.falcon.vbe
-#define VDB hw.falcon.vdb
-#define VDE hw.falcon.vde
-#define VSS hw.falcon.vss
-#define VCO_CLOCK25 0x04
-#define VCO_CSYPOS 0x10
-#define VCO_VSYPOS 0x20
-#define VCO_HSYPOS 0x40
-#define VCO_SHORTOFFS 0x100
-#define VMO_DOUBLE 0x01
-#define VMO_INTER 0x02
-#define VMO_PREMASK 0x0c
-#endif
-
-static struct fb_info fb_info = {
- .fix = {
- .id = "Atari ",
- .visual = FB_VISUAL_PSEUDOCOLOR,
- .accel = FB_ACCEL_NONE,
- }
-};
-
-static void *screen_base; /* base address of screen */
-static unsigned long phys_screen_base; /* (only for Overscan) */
-
-static int screen_len;
-
-static int current_par_valid;
-
-static int mono_moni;
-
-
-#ifdef ATAFB_EXT
-
-/* external video handling */
-static unsigned int external_xres;
-static unsigned int external_xres_virtual;
-static unsigned int external_yres;
-
-/*
- * not needed - atafb will never support panning/hardwarescroll with external
- * static unsigned int external_yres_virtual;
- */
-static unsigned int external_depth;
-static int external_pmode;
-static void *external_screen_base;
-static unsigned long external_addr;
-static unsigned long external_len;
-static unsigned long external_vgaiobase;
-static unsigned int external_bitspercol = 6;
-
-/*
- * JOE <joe@amber.dinoco.de>:
- * added card type for external driver, is only needed for
- * colormap handling.
- */
-enum cardtype { IS_VGA, IS_MV300 };
-static enum cardtype external_card_type = IS_VGA;
-
-/*
- * The MV300 mixes the color registers. So we need an array of munged
- * indices in order to access the correct reg.
- */
-static int MV300_reg_1bit[2] = {
- 0, 1
-};
-static int MV300_reg_4bit[16] = {
- 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
-};
-static int MV300_reg_8bit[256] = {
- 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
- 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
- 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
- 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
- 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
- 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
- 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
- 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
- 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
- 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
- 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
- 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
- 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
- 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
- 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
- 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
-};
-
-static int *MV300_reg = MV300_reg_8bit;
-#endif /* ATAFB_EXT */
-
-
-/*
- * struct fb_ops {
- * * open/release and usage marking
- * struct module *owner;
- * int (*fb_open)(struct fb_info *info, int user);
- * int (*fb_release)(struct fb_info *info, int user);
- *
- * * For framebuffers with strange non linear layouts or that do not
- * * work with normal memory mapped access
- * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
- * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
- *
- * * checks var and eventually tweaks it to something supported,
- * * DOES NOT MODIFY PAR *
- * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
- *
- * * set the video mode according to info->var *
- * int (*fb_set_par)(struct fb_info *info);
- *
- * * set color register *
- * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
- * unsigned int blue, unsigned int transp, struct fb_info *info);
- *
- * * set color registers in batch *
- * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
- *
- * * blank display *
- * int (*fb_blank)(int blank, struct fb_info *info);
- *
- * * pan display *
- * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
- *
- * *** The meat of the drawing engine ***
- * * Draws a rectangle *
- * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
- * * Copy data from area to another *
- * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
- * * Draws a image to the display *
- * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
- *
- * * Draws cursor *
- * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
- *
- * * wait for blit idle, optional *
- * int (*fb_sync)(struct fb_info *info);
- *
- * * perform fb specific ioctl (optional) *
- * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
- * unsigned long arg);
- *
- * * Handle 32bit compat ioctl (optional) *
- * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
- * unsigned long arg);
- *
- * * perform fb specific mmap *
- * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
- * } ;
- */
-
-
-/* ++roman: This structure abstracts from the underlying hardware (ST(e),
- * TT, or Falcon.
- *
- * int (*detect)(void)
- * This function should detect the current video mode settings and
- * store them in atafb_predefined[0] for later reference by the
- * user. Return the index+1 of an equivalent predefined mode or 0
- * if there is no such.
- *
- * int (*encode_fix)(struct fb_fix_screeninfo *fix,
- * struct atafb_par *par)
- * This function should fill in the 'fix' structure based on the
- * values in the 'par' structure.
- * !!! Obsolete, perhaps !!!
- *
- * int (*decode_var)(struct fb_var_screeninfo *var,
- * struct atafb_par *par)
- * Get the video params out of 'var'. If a value doesn't fit, round
- * it up, if it's too big, return EINVAL.
- * Round up in the following order: bits_per_pixel, xres, yres,
- * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
- * horizontal timing, vertical timing.
- *
- * int (*encode_var)(struct fb_var_screeninfo *var,
- * struct atafb_par *par);
- * Fill the 'var' structure based on the values in 'par' and maybe
- * other values read out of the hardware.
- *
- * void (*get_par)(struct atafb_par *par)
- * Fill the hardware's 'par' structure.
- * !!! Used only by detect() !!!
- *
- * void (*set_par)(struct atafb_par *par)
- * Set the hardware according to 'par'.
- *
- * void (*set_screen_base)(void *s_base)
- * Set the base address of the displayed frame buffer. Only called
- * if yres_virtual > yres or xres_virtual > xres.
- *
- * int (*blank)(int blank_mode)
- * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
- * the caller blanks by setting the CLUT to all black. Return 0 if blanking
- * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
- * doesn't support it. Implements VESA suspend and powerdown modes on
- * hardware that supports disabling hsync/vsync:
- * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
- */
-
-static struct fb_hwswitch {
- int (*detect)(void);
- int (*encode_fix)(struct fb_fix_screeninfo *fix,
- struct atafb_par *par);
- int (*decode_var)(struct fb_var_screeninfo *var,
- struct atafb_par *par);
- int (*encode_var)(struct fb_var_screeninfo *var,
- struct atafb_par *par);
- void (*get_par)(struct atafb_par *par);
- void (*set_par)(struct atafb_par *par);
- void (*set_screen_base)(void *s_base);
- int (*blank)(int blank_mode);
- int (*pan_display)(struct fb_var_screeninfo *var,
- struct fb_info *info);
-} *fbhw;
-
-static char *autodetect_names[] = { "autodetect", NULL };
-static char *stlow_names[] = { "stlow", NULL };
-static char *stmid_names[] = { "stmid", "default5", NULL };
-static char *sthigh_names[] = { "sthigh", "default4", NULL };
-static char *ttlow_names[] = { "ttlow", NULL };
-static char *ttmid_names[] = { "ttmid", "default1", NULL };
-static char *tthigh_names[] = { "tthigh", "default2", NULL };
-static char *vga2_names[] = { "vga2", NULL };
-static char *vga4_names[] = { "vga4", NULL };
-static char *vga16_names[] = { "vga16", "default3", NULL };
-static char *vga256_names[] = { "vga256", NULL };
-static char *falh2_names[] = { "falh2", NULL };
-static char *falh16_names[] = { "falh16", NULL };
-
-static char **fb_var_names[] = {
- autodetect_names,
- stlow_names,
- stmid_names,
- sthigh_names,
- ttlow_names,
- ttmid_names,
- tthigh_names,
- vga2_names,
- vga4_names,
- vga16_names,
- vga256_names,
- falh2_names,
- falh16_names,
- NULL
-};
-
-static struct fb_var_screeninfo atafb_predefined[] = {
- /*
- * yres_virtual == 0 means use hw-scrolling if possible, else yres
- */
- { /* autodetect */
- 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
- {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* st low */
- 320, 200, 320, 0, 0, 0, 4, 0,
- {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* st mid */
- 640, 200, 640, 0, 0, 0, 2, 0,
- {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* st high */
- 640, 400, 640, 0, 0, 0, 1, 0,
- {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* tt low */
- 320, 480, 320, 0, 0, 0, 8, 0,
- {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* tt mid */
- 640, 480, 640, 0, 0, 0, 4, 0,
- {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* tt high */
- 1280, 960, 1280, 0, 0, 0, 1, 0,
- {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* vga2 */
- 640, 480, 640, 0, 0, 0, 1, 0,
- {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* vga4 */
- 640, 480, 640, 0, 0, 0, 2, 0,
- {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* vga16 */
- 640, 480, 640, 0, 0, 0, 4, 0,
- {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* vga256 */
- 640, 480, 640, 0, 0, 0, 8, 0,
- {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* falh2 */
- 896, 608, 896, 0, 0, 0, 1, 0,
- {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { /* falh16 */
- 896, 608, 896, 0, 0, 0, 4, 0,
- {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-};
-
-static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
-
-static struct fb_videomode atafb_modedb[] __initdata = {
- /*
- * Atari Video Modes
- *
- * If you change these, make sure to update DEFMODE_* as well!
- */
-
- /*
- * ST/TT Video Modes
- */
-
- {
- /* 320x200, 15 kHz, 60 Hz (ST low) */
- "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 640x200, 15 kHz, 60 Hz (ST medium) */
- "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
- "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 320x480, 15 kHz, 60 Hz (TT low) */
- "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 640x480, 29 kHz, 57 Hz (TT medium) */
- "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 1280x960, 72 kHz, 72 Hz (TT high) */
- "tt-high", 72, 1280, 960, 7760, 260, 60, 36, 4, 192, 4,
- 0, FB_VMODE_NONINTERLACED
- },
-
- /*
- * VGA Video Modes
- */
-
- {
- /* 640x480, 31 kHz, 60 Hz (VGA) */
- "vga", 60, 640, 480, 39721, 42, 18, 31, 11, 100, 3,
- 0, FB_VMODE_NONINTERLACED
- }, {
- /* 640x400, 31 kHz, 70 Hz (VGA) */
- "vga70", 70, 640, 400, 39721, 42, 18, 31, 11, 100, 3,
- FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
- },
-
- /*
- * Falcon HiRes Video Modes
- */
-
- {
- /* 896x608, 31 kHz, 60 Hz (Falcon High) */
- "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
- 0, FB_VMODE_NONINTERLACED
- },
-};
-
-#define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb)
-
-static char *mode_option __initdata = NULL;
-
- /* default modes */
-
-#define DEFMODE_TT 5 /* "tt-high" for TT */
-#define DEFMODE_F30 7 /* "vga70" for Falcon */
-#define DEFMODE_STE 2 /* "st-high" for ST/E */
-#define DEFMODE_EXT 6 /* "vga" for external */
-
-
-static int get_video_mode(char *vname)
-{
- char ***name_list;
- char **name;
- int i;
-
- name_list = fb_var_names;
- for (i = 0; i < num_atafb_predefined; i++) {
- name = *name_list++;
- if (!name || !*name)
- break;
- while (*name) {
- if (!strcmp(vname, *name))
- return i + 1;
- name++;
- }
- }
- return 0;
-}
-
-
-
-/* ------------------- TT specific functions ---------------------- */
-
-#ifdef ATAFB_TT
-
-static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
-{
- int mode;
-
- strcpy(fix->id, "Atari Builtin");
- fix->smem_start = phys_screen_base;
- fix->smem_len = screen_len;
- fix->type = FB_TYPE_INTERLEAVED_PLANES;
- fix->type_aux = 2;
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
- mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
- if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- if (mode == TT_SHIFTER_TTHIGH)
- fix->visual = FB_VISUAL_MONO01;
- }
- fix->xpanstep = 0;
- fix->ypanstep = 1;
- fix->ywrapstep = 0;
- fix->line_length = par->next_line;
- fix->accel = FB_ACCEL_ATARIBLITT;
- return 0;
-}
-
-static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
-{
- int xres = var->xres;
- int yres = var->yres;
- int bpp = var->bits_per_pixel;
- int linelen;
- int yres_virtual = var->yres_virtual;
-
- if (mono_moni) {
- if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
- return -EINVAL;
- par->hw.tt.mode = TT_SHIFTER_TTHIGH;
- xres = sttt_xres * 2;
- yres = tt_yres * 2;
- bpp = 1;
- } else {
- if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
- return -EINVAL;
- if (bpp > 4) {
- if (xres > sttt_xres / 2 || yres > tt_yres)
- return -EINVAL;
- par->hw.tt.mode = TT_SHIFTER_TTLOW;
- xres = sttt_xres / 2;
- yres = tt_yres;
- bpp = 8;
- } else if (bpp > 2) {
- if (xres > sttt_xres || yres > tt_yres)
- return -EINVAL;
- if (xres > sttt_xres / 2 || yres > st_yres / 2) {
- par->hw.tt.mode = TT_SHIFTER_TTMID;
- xres = sttt_xres;
- yres = tt_yres;
- bpp = 4;
- } else {
- par->hw.tt.mode = TT_SHIFTER_STLOW;
- xres = sttt_xres / 2;
- yres = st_yres / 2;
- bpp = 4;
- }
- } else if (bpp > 1) {
- if (xres > sttt_xres || yres > st_yres / 2)
- return -EINVAL;
- par->hw.tt.mode = TT_SHIFTER_STMID;
- xres = sttt_xres;
- yres = st_yres / 2;
- bpp = 2;
- } else if (var->xres > sttt_xres || var->yres > st_yres) {
- return -EINVAL;
- } else {
- par->hw.tt.mode = TT_SHIFTER_STHIGH;
- xres = sttt_xres;
- yres = st_yres;
- bpp = 1;
- }
- }
- if (yres_virtual <= 0)
- yres_virtual = 0;
- else if (yres_virtual < yres)
- yres_virtual = yres;
- if (var->sync & FB_SYNC_EXT)
- par->hw.tt.sync = 0;
- else
- par->hw.tt.sync = 1;
- linelen = xres * bpp / 8;
- if (yres_virtual * linelen > screen_len && screen_len)
- return -EINVAL;
- if (yres * linelen > screen_len && screen_len)
- return -EINVAL;
- if (var->yoffset + yres > yres_virtual && yres_virtual)
- return -EINVAL;
- par->yres_virtual = yres_virtual;
- par->screen_base = screen_base + var->yoffset * linelen;
- par->next_line = linelen;
- return 0;
-}
-
-static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
-{
- int linelen;
- memset(var, 0, sizeof(struct fb_var_screeninfo));
- var->red.offset = 0;
- var->red.length = 4;
- var->red.msb_right = 0;
- var->grayscale = 0;
-
- var->pixclock = 31041;
- var->left_margin = 120; /* these may be incorrect */
- var->right_margin = 100;
- var->upper_margin = 8;
- var->lower_margin = 16;
- var->hsync_len = 140;
- var->vsync_len = 30;
-
- var->height = -1;
- var->width = -1;
-
- if (par->hw.tt.sync & 1)
- var->sync = 0;
- else
- var->sync = FB_SYNC_EXT;
-
- switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
- case TT_SHIFTER_STLOW:
- var->xres = sttt_xres / 2;
- var->xres_virtual = sttt_xres_virtual / 2;
- var->yres = st_yres / 2;
- var->bits_per_pixel = 4;
- break;
- case TT_SHIFTER_STMID:
- var->xres = sttt_xres;
- var->xres_virtual = sttt_xres_virtual;
- var->yres = st_yres / 2;
- var->bits_per_pixel = 2;
- break;
- case TT_SHIFTER_STHIGH:
- var->xres = sttt_xres;
- var->xres_virtual = sttt_xres_virtual;
- var->yres = st_yres;
- var->bits_per_pixel = 1;
- break;
- case TT_SHIFTER_TTLOW:
- var->xres = sttt_xres / 2;
- var->xres_virtual = sttt_xres_virtual / 2;
- var->yres = tt_yres;
- var->bits_per_pixel = 8;
- break;
- case TT_SHIFTER_TTMID:
- var->xres = sttt_xres;
- var->xres_virtual = sttt_xres_virtual;
- var->yres = tt_yres;
- var->bits_per_pixel = 4;
- break;
- case TT_SHIFTER_TTHIGH:
- var->red.length = 0;
- var->xres = sttt_xres * 2;
- var->xres_virtual = sttt_xres_virtual * 2;
- var->yres = tt_yres * 2;
- var->bits_per_pixel = 1;
- break;
- }
- var->blue = var->green = var->red;
- var->transp.offset = 0;
- var->transp.length = 0;
- var->transp.msb_right = 0;
- linelen = var->xres_virtual * var->bits_per_pixel / 8;
- if (!use_hwscroll)
- var->yres_virtual = var->yres;
- else if (screen_len) {
- if (par->yres_virtual)
- var->yres_virtual = par->yres_virtual;
- else
- /* yres_virtual == 0 means use maximum */
- var->yres_virtual = screen_len / linelen;
- } else {
- if (hwscroll < 0)
- var->yres_virtual = 2 * var->yres;
- else
- var->yres_virtual = var->yres + hwscroll * 16;
- }
- var->xoffset = 0;
- if (screen_base)
- var->yoffset = (par->screen_base - screen_base) / linelen;
- else
- var->yoffset = 0;
- var->nonstd = 0;
- var->activate = 0;
- var->vmode = FB_VMODE_NONINTERLACED;
- return 0;
-}
-
-static void tt_get_par(struct atafb_par *par)
-{
- unsigned long addr;
- par->hw.tt.mode = shifter_tt.tt_shiftmode;
- par->hw.tt.sync = shifter_st.syncmode;
- addr = ((shifter_st.bas_hi & 0xff) << 16) |
- ((shifter_st.bas_md & 0xff) << 8) |
- ((shifter_st.bas_lo & 0xff));
- par->screen_base = atari_stram_to_virt(addr);
-}
-
-static void tt_set_par(struct atafb_par *par)
-{
- shifter_tt.tt_shiftmode = par->hw.tt.mode;
- shifter_st.syncmode = par->hw.tt.sync;
- /* only set screen_base if really necessary */
- if (current_par.screen_base != par->screen_base)
- fbhw->set_screen_base(par->screen_base);
-}
-
-static int tt_setcolreg(unsigned int regno, unsigned int red,
- unsigned int green, unsigned int blue,
- unsigned int transp, struct fb_info *info)
-{
- if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
- regno += 254;
- if (regno > 255)
- return 1;
- tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
- (blue >> 12));
- if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
- TT_SHIFTER_STHIGH && regno == 254)
- tt_palette[0] = 0;
- return 0;
-}
-
-static int tt_detect(void)
-{
- struct atafb_par par;
-
- /* Determine the connected monitor: The DMA sound must be
- * disabled before reading the MFP GPIP, because the Sound
- * Done Signal and the Monochrome Detect are XORed together!
- *
- * Even on a TT, we should look if there is a DMA sound. It was
- * announced that the Eagle is TT compatible, but only the PCM is
- * missing...
- */
- if (ATARIHW_PRESENT(PCM_8BIT)) {
- tt_dmasnd.ctrl = DMASND_CTRL_OFF;
- udelay(20); /* wait a while for things to settle down */
- }
- mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
-
- tt_get_par(&par);
- tt_encode_var(&atafb_predefined[0], &par);
-
- return 1;
-}
-
-#endif /* ATAFB_TT */
-
-/* ------------------- Falcon specific functions ---------------------- */
-
-#ifdef ATAFB_FALCON
-
-static int mon_type; /* Falcon connected monitor */
-static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
-#define F_MON_SM 0
-#define F_MON_SC 1
-#define F_MON_VGA 2
-#define F_MON_TV 3
-
-static struct pixel_clock {
- unsigned long f; /* f/[Hz] */
- unsigned long t; /* t/[ps] (=1/f) */
- int right, hsync, left; /* standard timing in clock cycles, not pixel */
- /* hsync initialized in falcon_detect() */
- int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
- int control_mask; /* ditto, for hw.falcon.vid_control */
-} f25 = {
- 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
-}, f32 = {
- 32000000, 31250, 18, 0, 42, 0x0, 0
-}, fext = {
- 0, 0, 18, 0, 42, 0x1, 0
-};
-
-/* VIDEL-prescale values [mon_type][pixel_length from VCO] */
-static int vdl_prescale[4][3] = {
- { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
-};
-
-/* Default hsync timing [mon_type] in picoseconds */
-static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
-
-static inline int hxx_prescale(struct falcon_hw *hw)
-{
- return hw->ste_mode ? 16
- : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
-}
-
-static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
- struct atafb_par *par)
-{
- strcpy(fix->id, "Atari Builtin");
- fix->smem_start = phys_screen_base;
- fix->smem_len = screen_len;
- fix->type = FB_TYPE_INTERLEAVED_PLANES;
- fix->type_aux = 2;
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
- fix->xpanstep = 1;
- fix->ypanstep = 1;
- fix->ywrapstep = 0;
- if (par->hw.falcon.mono) {
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- /* no smooth scrolling with longword aligned video mem */
- fix->xpanstep = 32;
- } else if (par->hw.falcon.f_shift & 0x100) {
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- /* Is this ok or should it be DIRECTCOLOR? */
- fix->visual = FB_VISUAL_TRUECOLOR;
- fix->xpanstep = 2;
- }
- fix->line_length = par->next_line;
- fix->accel = FB_ACCEL_ATARIBLITT;
- return 0;
-}
-
-static int falcon_decode_var(struct fb_var_screeninfo *var,
- struct atafb_par *par)
-{
- int bpp = var->bits_per_pixel;
- int xres = var->xres;
- int yres = var->yres;
- int xres_virtual = var->xres_virtual;
- int yres_virtual = var->yres_virtual;
- int left_margin, right_margin, hsync_len;
- int upper_margin, lower_margin, vsync_len;
- int linelen;
- int interlace = 0, doubleline = 0;
- struct pixel_clock *pclock;
- int plen; /* width of pixel in clock cycles */
- int xstretch;
- int prescale;
- int longoffset = 0;
- int hfreq, vfreq;
- int hdb_off, hde_off, base_off;
- int gstart, gend1, gend2, align;
-
-/*
- Get the video params out of 'var'. If a value doesn't fit, round
- it up, if it's too big, return EINVAL.
- Round up in the following order: bits_per_pixel, xres, yres,
- xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
- horizontal timing, vertical timing.
-
- There is a maximum of screen resolution determined by pixelclock
- and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
- In interlace mode this is " * " *vfmin <= pixelclock.
- Additional constraints: hfreq.
- Frequency range for multisync monitors is given via command line.
- For TV and SM124 both frequencies are fixed.
-
- X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
- Y % 16 == 0 to fit 8x16 font
- Y % 8 == 0 if Y<400
-
- Currently interlace and doubleline mode in var are ignored.
- On SM124 and TV only the standard resolutions can be used.
-*/
-
- /* Reject uninitialized mode */
- if (!xres || !yres || !bpp)
- return -EINVAL;
-
- if (mon_type == F_MON_SM && bpp != 1)
- return -EINVAL;
-
- if (bpp <= 1) {
- bpp = 1;
- par->hw.falcon.f_shift = 0x400;
- par->hw.falcon.st_shift = 0x200;
- } else if (bpp <= 2) {
- bpp = 2;
- par->hw.falcon.f_shift = 0x000;
- par->hw.falcon.st_shift = 0x100;
- } else if (bpp <= 4) {
- bpp = 4;
- par->hw.falcon.f_shift = 0x000;
- par->hw.falcon.st_shift = 0x000;
- } else if (bpp <= 8) {
- bpp = 8;
- par->hw.falcon.f_shift = 0x010;
- } else if (bpp <= 16) {
- bpp = 16; /* packed pixel mode */
- par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
- } else
- return -EINVAL;
- par->hw.falcon.bpp = bpp;
-
- if (mon_type == F_MON_SM || DontCalcRes) {
- /* Skip all calculations. VGA/TV/SC1224 only supported. */
- struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-
- if (bpp > myvar->bits_per_pixel ||
- var->xres > myvar->xres ||
- var->yres > myvar->yres)
- return -EINVAL;
- fbhw->get_par(par); /* Current par will be new par */
- goto set_screen_base; /* Don't forget this */
- }
-
- /* Only some fixed resolutions < 640x400 */
- if (xres <= 320)
- xres = 320;
- else if (xres <= 640 && bpp != 16)
- xres = 640;
- if (yres <= 200)
- yres = 200;
- else if (yres <= 240)
- yres = 240;
- else if (yres <= 400)
- yres = 400;
-
- /* 2 planes must use STE compatibility mode */
- par->hw.falcon.ste_mode = bpp == 2;
- par->hw.falcon.mono = bpp == 1;
-
- /* Total and visible scanline length must be a multiple of one longword,
- * this and the console fontwidth yields the alignment for xres and
- * xres_virtual.
- * TODO: this way "odd" fontheights are not supported
- *
- * Special case in STE mode: blank and graphic positions don't align,
- * avoid trash at right margin
- */
- if (par->hw.falcon.ste_mode)
- xres = (xres + 63) & ~63;
- else if (bpp == 1)
- xres = (xres + 31) & ~31;
- else
- xres = (xres + 15) & ~15;
- if (yres >= 400)
- yres = (yres + 15) & ~15;
- else
- yres = (yres + 7) & ~7;
-
- if (xres_virtual < xres)
- xres_virtual = xres;
- else if (bpp == 1)
- xres_virtual = (xres_virtual + 31) & ~31;
- else
- xres_virtual = (xres_virtual + 15) & ~15;
-
- if (yres_virtual <= 0)
- yres_virtual = 0;
- else if (yres_virtual < yres)
- yres_virtual = yres;
-
- par->hw.falcon.line_width = bpp * xres / 16;
- par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
-
- /* single or double pixel width */
- xstretch = (xres < 640) ? 2 : 1;
-
-#if 0 /* SM124 supports only 640x400, this is rejected above */
- if (mon_type == F_MON_SM) {
- if (xres != 640 && yres != 400)
- return -EINVAL;
- plen = 1;
- pclock = &f32;
- /* SM124-mode is special */
- par->hw.falcon.ste_mode = 1;
- par->hw.falcon.f_shift = 0x000;
- par->hw.falcon.st_shift = 0x200;
- left_margin = hsync_len = 128 / plen;
- right_margin = 0;
- /* TODO set all margins */
- } else
-#endif
- if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
- plen = 2 * xstretch;
- if (var->pixclock > f32.t * plen)
- return -EINVAL;
- pclock = &f32;
- if (yres > 240)
- interlace = 1;
- if (var->pixclock == 0) {
- /* set some minimal margins which center the screen */
- left_margin = 32;
- right_margin = 18;
- hsync_len = pclock->hsync / plen;
- upper_margin = 31;
- lower_margin = 14;
- vsync_len = interlace ? 3 : 4;
- } else {
- left_margin = var->left_margin;
- right_margin = var->right_margin;
- hsync_len = var->hsync_len;
- upper_margin = var->upper_margin;
- lower_margin = var->lower_margin;
- vsync_len = var->vsync_len;
- if (var->vmode & FB_VMODE_INTERLACED) {
- upper_margin = (upper_margin + 1) / 2;
- lower_margin = (lower_margin + 1) / 2;
- vsync_len = (vsync_len + 1) / 2;
- } else if (var->vmode & FB_VMODE_DOUBLE) {
- upper_margin *= 2;
- lower_margin *= 2;
- vsync_len *= 2;
- }
- }
- } else { /* F_MON_VGA */
- if (bpp == 16)
- xstretch = 2; /* Double pixel width only for hicolor */
- /* Default values are used for vert./hor. timing if no pixelclock given. */
- if (var->pixclock == 0) {
- /* Choose master pixelclock depending on hor. timing */
- plen = 1 * xstretch;
- if ((plen * xres + f25.right + f25.hsync + f25.left) *
- fb_info.monspecs.hfmin < f25.f)
- pclock = &f25;
- else if ((plen * xres + f32.right + f32.hsync +
- f32.left) * fb_info.monspecs.hfmin < f32.f)
- pclock = &f32;
- else if ((plen * xres + fext.right + fext.hsync +
- fext.left) * fb_info.monspecs.hfmin < fext.f &&
- fext.f)
- pclock = &fext;
- else
- return -EINVAL;
-
- left_margin = pclock->left / plen;
- right_margin = pclock->right / plen;
- hsync_len = pclock->hsync / plen;
- upper_margin = 31;
- lower_margin = 11;
- vsync_len = 3;
- } else {
- /* Choose largest pixelclock <= wanted clock */
- int i;
- unsigned long pcl = ULONG_MAX;
- pclock = 0;
- for (i = 1; i <= 4; i *= 2) {
- if (f25.t * i >= var->pixclock &&
- f25.t * i < pcl) {
- pcl = f25.t * i;
- pclock = &f25;
- }
- if (f32.t * i >= var->pixclock &&
- f32.t * i < pcl) {
- pcl = f32.t * i;
- pclock = &f32;
- }
- if (fext.t && fext.t * i >= var->pixclock &&
- fext.t * i < pcl) {
- pcl = fext.t * i;
- pclock = &fext;
- }
- }
- if (!pclock)
- return -EINVAL;
- plen = pcl / pclock->t;
-
- left_margin = var->left_margin;
- right_margin = var->right_margin;
- hsync_len = var->hsync_len;
- upper_margin = var->upper_margin;
- lower_margin = var->lower_margin;
- vsync_len = var->vsync_len;
- /* Internal unit is [single lines per (half-)frame] */
- if (var->vmode & FB_VMODE_INTERLACED) {
- /* # lines in half frame */
- /* External unit is [lines per full frame] */
- upper_margin = (upper_margin + 1) / 2;
- lower_margin = (lower_margin + 1) / 2;
- vsync_len = (vsync_len + 1) / 2;
- } else if (var->vmode & FB_VMODE_DOUBLE) {
- /* External unit is [double lines per frame] */
- upper_margin *= 2;
- lower_margin *= 2;
- vsync_len *= 2;
- }
- }
- if (pclock == &fext)
- longoffset = 1; /* VIDEL doesn't synchronize on short offset */
- }
- /* Is video bus bandwidth (32MB/s) too low for this resolution? */
- /* this is definitely wrong if bus clock != 32MHz */
- if (pclock->f / plen / 8 * bpp > 32000000L)
- return -EINVAL;
-
- if (vsync_len < 1)
- vsync_len = 1;
-
- /* include sync lengths in right/lower margin for all calculations */
- right_margin += hsync_len;
- lower_margin += vsync_len;
-
- /* ! In all calculations of margins we use # of lines in half frame
- * (which is a full frame in non-interlace mode), so we can switch
- * between interlace and non-interlace without messing around
- * with these.
- */
-again:
- /* Set base_offset 128 and video bus width */
- par->hw.falcon.vid_control = mon_type | f030_bus_width;
- if (!longoffset)
- par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
- if (var->sync & FB_SYNC_HOR_HIGH_ACT)
- par->hw.falcon.vid_control |= VCO_HSYPOS;
- if (var->sync & FB_SYNC_VERT_HIGH_ACT)
- par->hw.falcon.vid_control |= VCO_VSYPOS;
- /* Pixelclock */
- par->hw.falcon.vid_control |= pclock->control_mask;
- /* External or internal clock */
- par->hw.falcon.sync = pclock->sync_mask | 0x2;
- /* Pixellength and prescale */
- par->hw.falcon.vid_mode = (2 / plen) << 2;
- if (doubleline)
- par->hw.falcon.vid_mode |= VMO_DOUBLE;
- if (interlace)
- par->hw.falcon.vid_mode |= VMO_INTER;
-
- /*********************
- * Horizontal timing: unit = [master clock cycles]
- * unit of hxx-registers: [master clock cycles * prescale]
- * Hxx-registers are 9 bit wide
- *
- * 1 line = ((hht + 2) * 2 * prescale) clock cycles
- *
- * graphic output = hdb & 0x200 ?
- * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
- * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
- * (this must be a multiple of plen*128/bpp, on VGA pixels
- * to the right may be cut off with a bigger right margin)
- *
- * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
- * (hdb - hht - 2) * prescale + hdboff :
- * hdb * prescale + hdboff
- *
- * end of graphics relative to start of 1st halfline =
- * (hde + hht + 2) * prescale + hdeoff
- *********************/
- /* Calculate VIDEL registers */
-{
- prescale = hxx_prescale(&par->hw.falcon);
- base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
-
- /* Offsets depend on video mode */
- /* Offsets are in clock cycles, divide by prescale to
- * calculate hd[be]-registers
- */
- if (par->hw.falcon.f_shift & 0x100) {
- align = 1;
- hde_off = 0;
- hdb_off = (base_off + 16 * plen) + prescale;
- } else {
- align = 128 / bpp;
- hde_off = ((128 / bpp + 2) * plen);
- if (par->hw.falcon.ste_mode)
- hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
- else
- hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
- }
-
- gstart = (prescale / 2 + plen * left_margin) / prescale;
- /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
- gend1 = gstart + roundup(xres, align) * plen / prescale;
- /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
- gend2 = gstart + xres * plen / prescale;
- par->HHT = plen * (left_margin + xres + right_margin) /
- (2 * prescale) - 2;
-/* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
-
- par->HDB = gstart - hdb_off / prescale;
- par->HBE = gstart;
- if (par->HDB < 0)
- par->HDB += par->HHT + 2 + 0x200;
- par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
- par->HBB = gend2 - par->HHT - 2;
-#if 0
- /* One more Videl constraint: data fetch of two lines must not overlap */
- if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
- /* if this happens increase margins, decrease hfreq. */
- }
-#endif
- if (hde_off % prescale)
- par->HBB++; /* compensate for non matching hde and hbb */
- par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
- if (par->HSS < par->HBB)
- par->HSS = par->HBB;
-}
-
- /* check hor. frequency */
- hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
- if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
- /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
- /* Too high -> enlarge margin */
- left_margin += 1;
- right_margin += 1;
- goto again;
- }
- if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
- return -EINVAL;
-
- /* Vxx-registers */
- /* All Vxx must be odd in non-interlace, since frame starts in the middle
- * of the first displayed line!
- * One frame consists of VFT+1 half lines. VFT+1 must be even in
- * non-interlace, odd in interlace mode for synchronisation.
- * Vxx-registers are 11 bit wide
- */
- par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
- par->VDB = par->VBE;
- par->VDE = yres;
- if (!interlace)
- par->VDE <<= 1;
- if (doubleline)
- par->VDE <<= 1; /* VDE now half lines per (half-)frame */
- par->VDE += par->VDB;
- par->VBB = par->VDE;
- par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
- par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
- /* vbb,vss,vft must be even in interlace mode */
- if (interlace) {
- par->VBB++;
- par->VSS++;
- par->VFT++;
- }
-
- /* V-frequency check, hope I didn't create any loop here. */
- /* Interlace and doubleline are mutually exclusive. */
- vfreq = (hfreq * 2) / (par->VFT + 1);
- if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
- /* Too high -> try again with doubleline */
- doubleline = 1;
- goto again;
- } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
- /* Too low -> try again with interlace */
- interlace = 1;
- goto again;
- } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
- /* Doubleline too low -> clear doubleline and enlarge margins */
- int lines;
- doubleline = 0;
- for (lines = 0;
- (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
- fb_info.monspecs.vfmax;
- lines++)
- ;
- upper_margin += lines;
- lower_margin += lines;
- goto again;
- } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
- /* Doubleline too high -> enlarge margins */
- int lines;
- for (lines = 0;
- (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
- fb_info.monspecs.vfmax;
- lines += 2)
- ;
- upper_margin += lines;
- lower_margin += lines;
- goto again;
- } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
- /* Interlace, too high -> enlarge margins */
- int lines;
- for (lines = 0;
- (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
- fb_info.monspecs.vfmax;
- lines++)
- ;
- upper_margin += lines;
- lower_margin += lines;
- goto again;
- } else if (vfreq < fb_info.monspecs.vfmin ||
- vfreq > fb_info.monspecs.vfmax)
- return -EINVAL;
-
-set_screen_base:
- linelen = xres_virtual * bpp / 8;
- if (yres_virtual * linelen > screen_len && screen_len)
- return -EINVAL;
- if (yres * linelen > screen_len && screen_len)
- return -EINVAL;
- if (var->yoffset + yres > yres_virtual && yres_virtual)
- return -EINVAL;
- par->yres_virtual = yres_virtual;
- par->screen_base = screen_base + var->yoffset * linelen;
- par->hw.falcon.xoffset = 0;
-
- par->next_line = linelen;
-
- return 0;
-}
-
-static int falcon_encode_var(struct fb_var_screeninfo *var,
- struct atafb_par *par)
-{
-/* !!! only for VGA !!! */
- int linelen;
- int prescale, plen;
- int hdb_off, hde_off, base_off;
- struct falcon_hw *hw = &par->hw.falcon;
-
- memset(var, 0, sizeof(struct fb_var_screeninfo));
- /* possible frequencies: 25.175 or 32MHz */
- var->pixclock = hw->sync & 0x1 ? fext.t :
- hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
-
- var->height = -1;
- var->width = -1;
-
- var->sync = 0;
- if (hw->vid_control & VCO_HSYPOS)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (hw->vid_control & VCO_VSYPOS)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
- var->vmode = FB_VMODE_NONINTERLACED;
- if (hw->vid_mode & VMO_INTER)
- var->vmode |= FB_VMODE_INTERLACED;
- if (hw->vid_mode & VMO_DOUBLE)
- var->vmode |= FB_VMODE_DOUBLE;
-
- /* visible y resolution:
- * Graphics display starts at line VDB and ends at line
- * VDE. If interlace mode off unit of VC-registers is
- * half lines, else lines.
- */
- var->yres = hw->vde - hw->vdb;
- if (!(var->vmode & FB_VMODE_INTERLACED))
- var->yres >>= 1;
- if (var->vmode & FB_VMODE_DOUBLE)
- var->yres >>= 1;
-
- /*
- * to get bpp, we must examine f_shift and st_shift.
- * f_shift is valid if any of bits no. 10, 8 or 4
- * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
- * if bit 10 set then bit 8 and bit 4 don't care...
- * If all these bits are 0 get display depth from st_shift
- * (as for ST and STE)
- */
- if (hw->f_shift & 0x400) /* 2 colors */
- var->bits_per_pixel = 1;
- else if (hw->f_shift & 0x100) /* hicolor */
- var->bits_per_pixel = 16;
- else if (hw->f_shift & 0x010) /* 8 bitplanes */
- var->bits_per_pixel = 8;
- else if (hw->st_shift == 0)
- var->bits_per_pixel = 4;
- else if (hw->st_shift == 0x100)
- var->bits_per_pixel = 2;
- else /* if (hw->st_shift == 0x200) */
- var->bits_per_pixel = 1;
-
- var->xres = hw->line_width * 16 / var->bits_per_pixel;
- var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
- if (hw->xoffset)
- var->xres_virtual += 16;
-
- if (var->bits_per_pixel == 16) {
- var->red.offset = 11;
- var->red.length = 5;
- var->red.msb_right = 0;
- var->green.offset = 5;
- var->green.length = 6;
- var->green.msb_right = 0;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->blue.msb_right = 0;
- } else {
- var->red.offset = 0;
- var->red.length = hw->ste_mode ? 4 : 6;
- if (var->red.length > var->bits_per_pixel)
- var->red.length = var->bits_per_pixel;
- var->red.msb_right = 0;
- var->grayscale = 0;
- var->blue = var->green = var->red;
- }
- var->transp.offset = 0;
- var->transp.length = 0;
- var->transp.msb_right = 0;
-
- linelen = var->xres_virtual * var->bits_per_pixel / 8;
- if (screen_len) {
- if (par->yres_virtual)
- var->yres_virtual = par->yres_virtual;
- else
- /* yres_virtual == 0 means use maximum */
- var->yres_virtual = screen_len / linelen;
- } else {
- if (hwscroll < 0)
- var->yres_virtual = 2 * var->yres;
- else
- var->yres_virtual = var->yres + hwscroll * 16;
- }
- var->xoffset = 0; /* TODO change this */
-
- /* hdX-offsets */
- prescale = hxx_prescale(hw);
- plen = 4 >> (hw->vid_mode >> 2 & 0x3);
- base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
- if (hw->f_shift & 0x100) {
- hde_off = 0;
- hdb_off = (base_off + 16 * plen) + prescale;
- } else {
- hde_off = ((128 / var->bits_per_pixel + 2) * plen);
- if (hw->ste_mode)
- hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
- + prescale;
- else
- hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
- + prescale;
- }
-
- /* Right margin includes hsync */
- var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
- (hw->hdb & 0x200 ? 2 + hw->hht : 0));
- if (hw->ste_mode || mon_type != F_MON_VGA)
- var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
- else
- /* can't use this in ste_mode, because hbb is +1 off */
- var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
- var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
-
- /* Lower margin includes vsync */
- var->upper_margin = hw->vdb / 2; /* round down to full lines */
- var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */
- var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */
- if (var->vmode & FB_VMODE_INTERLACED) {
- var->upper_margin *= 2;
- var->lower_margin *= 2;
- var->vsync_len *= 2;
- } else if (var->vmode & FB_VMODE_DOUBLE) {
- var->upper_margin = (var->upper_margin + 1) / 2;
- var->lower_margin = (var->lower_margin + 1) / 2;
- var->vsync_len = (var->vsync_len + 1) / 2;
- }
-
- var->pixclock *= plen;
- var->left_margin /= plen;
- var->right_margin /= plen;
- var->hsync_len /= plen;
-
- var->right_margin -= var->hsync_len;
- var->lower_margin -= var->vsync_len;
-
- if (screen_base)
- var->yoffset = (par->screen_base - screen_base) / linelen;
- else
- var->yoffset = 0;
- var->nonstd = 0; /* what is this for? */
- var->activate = 0;
- return 0;
-}
-
-static int f_change_mode;
-static struct falcon_hw f_new_mode;
-static int f_pan_display;
-
-static void falcon_get_par(struct atafb_par *par)
-{
- unsigned long addr;
- struct falcon_hw *hw = &par->hw.falcon;
-
- hw->line_width = shifter_f030.scn_width;
- hw->line_offset = shifter_f030.off_next;
- hw->st_shift = videl.st_shift & 0x300;
- hw->f_shift = videl.f_shift;
- hw->vid_control = videl.control;
- hw->vid_mode = videl.mode;
- hw->sync = shifter_st.syncmode & 0x1;
- hw->xoffset = videl.xoffset & 0xf;
- hw->hht = videl.hht;
- hw->hbb = videl.hbb;
- hw->hbe = videl.hbe;
- hw->hdb = videl.hdb;
- hw->hde = videl.hde;
- hw->hss = videl.hss;
- hw->vft = videl.vft;
- hw->vbb = videl.vbb;
- hw->vbe = videl.vbe;
- hw->vdb = videl.vdb;
- hw->vde = videl.vde;
- hw->vss = videl.vss;
-
- addr = (shifter_st.bas_hi & 0xff) << 16 |
- (shifter_st.bas_md & 0xff) << 8 |
- (shifter_st.bas_lo & 0xff);
- par->screen_base = atari_stram_to_virt(addr);
-
- /* derived parameters */
- hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
- hw->mono = (hw->f_shift & 0x400) ||
- ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
-}
-
-static void falcon_set_par(struct atafb_par *par)
-{
- f_change_mode = 0;
-
- /* only set screen_base if really necessary */
- if (current_par.screen_base != par->screen_base)
- fbhw->set_screen_base(par->screen_base);
-
- /* Don't touch any other registers if we keep the default resolution */
- if (DontCalcRes)
- return;
-
- /* Tell vbl-handler to change video mode.
- * We change modes only on next VBL, to avoid desynchronisation
- * (a shift to the right and wrap around by a random number of pixels
- * in all monochrome modes).
- * This seems to work on my Falcon.
- */
- f_new_mode = par->hw.falcon;
- f_change_mode = 1;
-}
-
-static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
-{
- struct falcon_hw *hw = &f_new_mode;
-
- if (f_change_mode) {
- f_change_mode = 0;
-
- if (hw->sync & 0x1) {
- /* Enable external pixelclock. This code only for ScreenWonder */
- *(volatile unsigned short *)0xffff9202 = 0xffbf;
- } else {
- /* Turn off external clocks. Read sets all output bits to 1. */
- *(volatile unsigned short *)0xffff9202;
- }
- shifter_st.syncmode = hw->sync;
-
- videl.hht = hw->hht;
- videl.hbb = hw->hbb;
- videl.hbe = hw->hbe;
- videl.hdb = hw->hdb;
- videl.hde = hw->hde;
- videl.hss = hw->hss;
- videl.vft = hw->vft;
- videl.vbb = hw->vbb;
- videl.vbe = hw->vbe;
- videl.vdb = hw->vdb;
- videl.vde = hw->vde;
- videl.vss = hw->vss;
-
- videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
- if (hw->ste_mode) {
- videl.st_shift = hw->st_shift; /* write enables STE palette */
- } else {
- /* IMPORTANT:
- * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
- * Writing 0 to f_shift enables 4 plane Falcon mode but
- * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
- * with Falcon palette.
- */
- videl.st_shift = 0;
- /* now back to Falcon palette mode */
- videl.f_shift = hw->f_shift;
- }
- /* writing to st_shift changed scn_width and vid_mode */
- videl.xoffset = hw->xoffset;
- shifter_f030.scn_width = hw->line_width;
- shifter_f030.off_next = hw->line_offset;
- videl.control = hw->vid_control;
- videl.mode = hw->vid_mode;
- }
- if (f_pan_display) {
- f_pan_display = 0;
- videl.xoffset = current_par.hw.falcon.xoffset;
- shifter_f030.off_next = current_par.hw.falcon.line_offset;
- }
- return IRQ_HANDLED;
-}
-
-static int falcon_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- struct atafb_par *par = info->par;
-
- int xoffset;
- int bpp = info->var.bits_per_pixel;
-
- if (bpp == 1)
- var->xoffset = round_up(var->xoffset, 32);
- if (bpp != 16)
- par->hw.falcon.xoffset = var->xoffset & 15;
- else {
- par->hw.falcon.xoffset = 0;
- var->xoffset = round_up(var->xoffset, 2);
- }
- par->hw.falcon.line_offset = bpp *
- (info->var.xres_virtual - info->var.xres) / 16;
- if (par->hw.falcon.xoffset)
- par->hw.falcon.line_offset -= bpp;
- xoffset = var->xoffset - par->hw.falcon.xoffset;
-
- par->screen_base = screen_base +
- (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
- if (fbhw->set_screen_base)
- fbhw->set_screen_base(par->screen_base);
- else
- return -EINVAL; /* shouldn't happen */
- f_pan_display = 1;
- return 0;
-}
-
-static int falcon_setcolreg(unsigned int regno, unsigned int red,
- unsigned int green, unsigned int blue,
- unsigned int transp, struct fb_info *info)
-{
- if (regno > 255)
- return 1;
- f030_col[regno] = (((red & 0xfc00) << 16) |
- ((green & 0xfc00) << 8) |
- ((blue & 0xfc00) >> 8));
- if (regno < 16) {
- shifter_tt.color_reg[regno] =
- ((((red & 0xe000) >> 13) | ((red & 0x1000) >> 12)) << 8) |
- ((((green & 0xe000) >> 13) | ((green & 0x1000) >> 12)) << 4) |
- ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
- ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
- ((green & 0xfc00) >> 5) |
- ((blue & 0xf800) >> 11));
- }
- return 0;
-}
-
-static int falcon_blank(int blank_mode)
-{
- /* ++guenther: we can switch off graphics by changing VDB and VDE,
- * so VIDEL doesn't hog the bus while saving.
- * (this may affect usleep()).
- */
- int vdb, vss, hbe, hss;
-
- if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
- return 1;
-
- vdb = current_par.VDB;
- vss = current_par.VSS;
- hbe = current_par.HBE;
- hss = current_par.HSS;
-
- if (blank_mode >= 1) {
- /* disable graphics output (this speeds up the CPU) ... */
- vdb = current_par.VFT + 1;
- /* ... and blank all lines */
- hbe = current_par.HHT + 2;
- }
- /* use VESA suspend modes on VGA monitors */
- if (mon_type == F_MON_VGA) {
- if (blank_mode == 2 || blank_mode == 4)
- vss = current_par.VFT + 1;
- if (blank_mode == 3 || blank_mode == 4)
- hss = current_par.HHT + 2;
- }
-
- videl.vdb = vdb;
- videl.vss = vss;
- videl.hbe = hbe;
- videl.hss = hss;
-
- return 0;
-}
-
-static int falcon_detect(void)
-{
- struct atafb_par par;
- unsigned char fhw;
-
- /* Determine connected monitor and set monitor parameters */
- fhw = *(unsigned char *)0xffff8006;
- mon_type = fhw >> 6 & 0x3;
- /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
- f030_bus_width = fhw << 6 & 0x80;
- switch (mon_type) {
- case F_MON_SM:
- fb_info.monspecs.vfmin = 70;
- fb_info.monspecs.vfmax = 72;
- fb_info.monspecs.hfmin = 35713;
- fb_info.monspecs.hfmax = 35715;
- break;
- case F_MON_SC:
- case F_MON_TV:
- /* PAL...NTSC */
- fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
- fb_info.monspecs.vfmax = 60;
- fb_info.monspecs.hfmin = 15620;
- fb_info.monspecs.hfmax = 15755;
- break;
- }
- /* initialize hsync-len */
- f25.hsync = h_syncs[mon_type] / f25.t;
- f32.hsync = h_syncs[mon_type] / f32.t;
- if (fext.t)
- fext.hsync = h_syncs[mon_type] / fext.t;
-
- falcon_get_par(&par);
- falcon_encode_var(&atafb_predefined[0], &par);
-
- /* Detected mode is always the "autodetect" slot */
- return 1;
-}
-
-#endif /* ATAFB_FALCON */
-
-/* ------------------- ST(E) specific functions ---------------------- */
-
-#ifdef ATAFB_STE
-
-static int stste_encode_fix(struct fb_fix_screeninfo *fix,
- struct atafb_par *par)
-{
- int mode;
-
- strcpy(fix->id, "Atari Builtin");
- fix->smem_start = phys_screen_base;
- fix->smem_len = screen_len;
- fix->type = FB_TYPE_INTERLEAVED_PLANES;
- fix->type_aux = 2;
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
- mode = par->hw.st.mode & 3;
- if (mode == ST_HIGH) {
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- fix->visual = FB_VISUAL_MONO10;
- }
- if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
- fix->xpanstep = 16;
- fix->ypanstep = 1;
- } else {
- fix->xpanstep = 0;
- fix->ypanstep = 0;
- }
- fix->ywrapstep = 0;
- fix->line_length = par->next_line;
- fix->accel = FB_ACCEL_ATARIBLITT;
- return 0;
-}
-
-static int stste_decode_var(struct fb_var_screeninfo *var,
- struct atafb_par *par)
-{
- int xres = var->xres;
- int yres = var->yres;
- int bpp = var->bits_per_pixel;
- int linelen;
- int yres_virtual = var->yres_virtual;
-
- if (mono_moni) {
- if (bpp > 1 || xres > sttt_xres || yres > st_yres)
- return -EINVAL;
- par->hw.st.mode = ST_HIGH;
- xres = sttt_xres;
- yres = st_yres;
- bpp = 1;
- } else {
- if (bpp > 4 || xres > sttt_xres || yres > st_yres)
- return -EINVAL;
- if (bpp > 2) {
- if (xres > sttt_xres / 2 || yres > st_yres / 2)
- return -EINVAL;
- par->hw.st.mode = ST_LOW;
- xres = sttt_xres / 2;
- yres = st_yres / 2;
- bpp = 4;
- } else if (bpp > 1) {
- if (xres > sttt_xres || yres > st_yres / 2)
- return -EINVAL;
- par->hw.st.mode = ST_MID;
- xres = sttt_xres;
- yres = st_yres / 2;
- bpp = 2;
- } else
- return -EINVAL;
- }
- if (yres_virtual <= 0)
- yres_virtual = 0;
- else if (yres_virtual < yres)
- yres_virtual = yres;
- if (var->sync & FB_SYNC_EXT)
- par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
- else
- par->hw.st.sync = (par->hw.st.sync & ~1);
- linelen = xres * bpp / 8;
- if (yres_virtual * linelen > screen_len && screen_len)
- return -EINVAL;
- if (yres * linelen > screen_len && screen_len)
- return -EINVAL;
- if (var->yoffset + yres > yres_virtual && yres_virtual)
- return -EINVAL;
- par->yres_virtual = yres_virtual;
- par->screen_base = screen_base + var->yoffset * linelen;
- par->next_line = linelen;
- return 0;
-}
-
-static int stste_encode_var(struct fb_var_screeninfo *var,
- struct atafb_par *par)
-{
- int linelen;
- memset(var, 0, sizeof(struct fb_var_screeninfo));
- var->red.offset = 0;
- var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
- var->red.msb_right = 0;
- var->grayscale = 0;
-
- var->pixclock = 31041;
- var->left_margin = 120; /* these are incorrect */
- var->right_margin = 100;
- var->upper_margin = 8;
- var->lower_margin = 16;
- var->hsync_len = 140;
- var->vsync_len = 30;
-
- var->height = -1;
- var->width = -1;
-
- if (!(par->hw.st.sync & 1))
- var->sync = 0;
- else
- var->sync = FB_SYNC_EXT;
-
- switch (par->hw.st.mode & 3) {
- case ST_LOW:
- var->xres = sttt_xres / 2;
- var->yres = st_yres / 2;
- var->bits_per_pixel = 4;
- break;
- case ST_MID:
- var->xres = sttt_xres;
- var->yres = st_yres / 2;
- var->bits_per_pixel = 2;
- break;
- case ST_HIGH:
- var->xres = sttt_xres;
- var->yres = st_yres;
- var->bits_per_pixel = 1;
- break;
- }
- var->blue = var->green = var->red;
- var->transp.offset = 0;
- var->transp.length = 0;
- var->transp.msb_right = 0;
- var->xres_virtual = sttt_xres_virtual;
- linelen = var->xres_virtual * var->bits_per_pixel / 8;
- ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
-
- if (!use_hwscroll)
- var->yres_virtual = var->yres;
- else if (screen_len) {
- if (par->yres_virtual)
- var->yres_virtual = par->yres_virtual;
- else
- /* yres_virtual == 0 means use maximum */
- var->yres_virtual = screen_len / linelen;
- } else {
- if (hwscroll < 0)
- var->yres_virtual = 2 * var->yres;
- else
- var->yres_virtual = var->yres + hwscroll * 16;
- }
- var->xoffset = 0;
- if (screen_base)
- var->yoffset = (par->screen_base - screen_base) / linelen;
- else
- var->yoffset = 0;
- var->nonstd = 0;
- var->activate = 0;
- var->vmode = FB_VMODE_NONINTERLACED;
- return 0;
-}
-
-static void stste_get_par(struct atafb_par *par)
-{
- unsigned long addr;
- par->hw.st.mode = shifter_tt.st_shiftmode;
- par->hw.st.sync = shifter_st.syncmode;
- addr = ((shifter_st.bas_hi & 0xff) << 16) |
- ((shifter_st.bas_md & 0xff) << 8);
- if (ATARIHW_PRESENT(EXTD_SHIFTER))
- addr |= (shifter_st.bas_lo & 0xff);
- par->screen_base = atari_stram_to_virt(addr);
-}
-
-static void stste_set_par(struct atafb_par *par)
-{
- shifter_tt.st_shiftmode = par->hw.st.mode;
- shifter_st.syncmode = par->hw.st.sync;
- /* only set screen_base if really necessary */
- if (current_par.screen_base != par->screen_base)
- fbhw->set_screen_base(par->screen_base);
-}
-
-static int stste_setcolreg(unsigned int regno, unsigned int red,
- unsigned int green, unsigned int blue,
- unsigned int transp, struct fb_info *info)
-{
- if (regno > 15)
- return 1;
- red >>= 12;
- blue >>= 12;
- green >>= 12;
- if (ATARIHW_PRESENT(EXTD_SHIFTER))
- shifter_tt.color_reg[regno] =
- ((((red & 0xe) >> 1) | ((red & 1) << 3)) << 8) |
- ((((green & 0xe) >> 1) | ((green & 1) << 3)) << 4) |
- ((blue & 0xe) >> 1) | ((blue & 1) << 3);
- else
- shifter_tt.color_reg[regno] =
- ((red & 0xe) << 7) |
- ((green & 0xe) << 3) |
- ((blue & 0xe) >> 1);
- return 0;
-}
-
-static int stste_detect(void)
-{
- struct atafb_par par;
-
- /* Determine the connected monitor: The DMA sound must be
- * disabled before reading the MFP GPIP, because the Sound
- * Done Signal and the Monochrome Detect are XORed together!
- */
- if (ATARIHW_PRESENT(PCM_8BIT)) {
- tt_dmasnd.ctrl = DMASND_CTRL_OFF;
- udelay(20); /* wait a while for things to settle down */
- }
- mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
-
- stste_get_par(&par);
- stste_encode_var(&atafb_predefined[0], &par);
-
- if (!ATARIHW_PRESENT(EXTD_SHIFTER))
- use_hwscroll = 0;
- return 1;
-}
-
-static void stste_set_screen_base(void *s_base)
-{
- unsigned long addr;
- addr = atari_stram_to_phys(s_base);
- /* Setup Screen Memory */
- shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
- shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
- if (ATARIHW_PRESENT(EXTD_SHIFTER))
- shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
-}
-
-#endif /* ATAFB_STE */
-
-/* Switching the screen size should be done during vsync, otherwise
- * the margins may get messed up. This is a well known problem of
- * the ST's video system.
- *
- * Unfortunately there is hardly any way to find the vsync, as the
- * vertical blank interrupt is no longer in time on machines with
- * overscan type modifications.
- *
- * We can, however, use Timer B to safely detect the black shoulder,
- * but then we've got to guess an appropriate delay to find the vsync.
- * This might not work on every machine.
- *
- * martin_rogge @ ki.maus.de, 8th Aug 1995
- */
-
-#define LINE_DELAY (mono_moni ? 30 : 70)
-#define SYNC_DELAY (mono_moni ? 1500 : 2000)
-
-/* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
-static void st_ovsc_switch(void)
-{
- unsigned long flags;
- register unsigned char old, new;
-
- if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
- return;
- local_irq_save(flags);
-
- st_mfp.tim_ct_b = 0x10;
- st_mfp.active_edge |= 8;
- st_mfp.tim_ct_b = 0;
- st_mfp.tim_dt_b = 0xf0;
- st_mfp.tim_ct_b = 8;
- while (st_mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
- ;
- new = st_mfp.tim_dt_b;
- do {
- udelay(LINE_DELAY);
- old = new;
- new = st_mfp.tim_dt_b;
- } while (old != new);
- st_mfp.tim_ct_b = 0x10;
- udelay(SYNC_DELAY);
-
- if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
- acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
- if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
- acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
- if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
- sound_ym.rd_data_reg_sel = 14;
- sound_ym.wd_data = sound_ym.rd_data_reg_sel |
- ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
- ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
- }
- local_irq_restore(flags);
-}
-
-/* ------------------- External Video ---------------------- */
-
-#ifdef ATAFB_EXT
-
-static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
-{
- strcpy(fix->id, "Unknown Extern");
- fix->smem_start = external_addr;
- fix->smem_len = PAGE_ALIGN(external_len);
- if (external_depth == 1) {
- fix->type = FB_TYPE_PACKED_PIXELS;
- /* The letters 'n' and 'i' in the "atavideo=external:" stand
- * for "normal" and "inverted", rsp., in the monochrome case */
- fix->visual =
- (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
- external_pmode == FB_TYPE_PACKED_PIXELS) ?
- FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
- } else {
- /* Use STATIC if we don't know how to access color registers */
- int visual = external_vgaiobase ?
- FB_VISUAL_PSEUDOCOLOR :
- FB_VISUAL_STATIC_PSEUDOCOLOR;
- switch (external_pmode) {
- case -1: /* truecolor */
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->visual = FB_VISUAL_TRUECOLOR;
- break;
- case FB_TYPE_PACKED_PIXELS:
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->visual = visual;
- break;
- case FB_TYPE_PLANES:
- fix->type = FB_TYPE_PLANES;
- fix->visual = visual;
- break;
- case FB_TYPE_INTERLEAVED_PLANES:
- fix->type = FB_TYPE_INTERLEAVED_PLANES;
- fix->type_aux = 2;
- fix->visual = visual;
- break;
- }
- }
- fix->xpanstep = 0;
- fix->ypanstep = 0;
- fix->ywrapstep = 0;
- fix->line_length = par->next_line;
- return 0;
-}
-
-static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
-{
- struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-
- if (var->bits_per_pixel > myvar->bits_per_pixel ||
- var->xres > myvar->xres ||
- var->xres_virtual > myvar->xres_virtual ||
- var->yres > myvar->yres ||
- var->xoffset > 0 ||
- var->yoffset > 0)
- return -EINVAL;
-
- par->next_line = external_xres_virtual * external_depth / 8;
- return 0;
-}
-
-static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
-{
- memset(var, 0, sizeof(struct fb_var_screeninfo));
- var->red.offset = 0;
- var->red.length = (external_pmode == -1) ? external_depth / 3 :
- (external_vgaiobase ? external_bitspercol : 0);
- var->red.msb_right = 0;
- var->grayscale = 0;
-
- var->pixclock = 31041;
- var->left_margin = 120; /* these are surely incorrect */
- var->right_margin = 100;
- var->upper_margin = 8;
- var->lower_margin = 16;
- var->hsync_len = 140;
- var->vsync_len = 30;
-
- var->height = -1;
- var->width = -1;
-
- var->sync = 0;
-
- var->xres = external_xres;
- var->yres = external_yres;
- var->xres_virtual = external_xres_virtual;
- var->bits_per_pixel = external_depth;
-
- var->blue = var->green = var->red;
- var->transp.offset = 0;
- var->transp.length = 0;
- var->transp.msb_right = 0;
- var->yres_virtual = var->yres;
- var->xoffset = 0;
- var->yoffset = 0;
- var->nonstd = 0;
- var->activate = 0;
- var->vmode = FB_VMODE_NONINTERLACED;
- return 0;
-}
-
-static void ext_get_par(struct atafb_par *par)
-{
- par->screen_base = external_screen_base;
-}
-
-static void ext_set_par(struct atafb_par *par)
-{
-}
-
-#define OUTB(port,val) \
- *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
-#define INB(port) \
- (*((unsigned volatile char *) ((port)+external_vgaiobase)))
-#define DACDelay \
- do { \
- unsigned char tmp = INB(0x3da); \
- tmp = INB(0x3da); \
- } while (0)
-
-static int ext_setcolreg(unsigned int regno, unsigned int red,
- unsigned int green, unsigned int blue,
- unsigned int transp, struct fb_info *info)
-{
- unsigned char colmask = (1 << external_bitspercol) - 1;
-
- if (!external_vgaiobase)
- return 1;
-
- if (regno > 255)
- return 1;
-
- red >>= 8;
- green >>= 8;
- blue >>= 8;
-
- switch (external_card_type) {
- case IS_VGA:
- OUTB(0x3c8, regno);
- DACDelay;
- OUTB(0x3c9, red & colmask);
- DACDelay;
- OUTB(0x3c9, green & colmask);
- DACDelay;
- OUTB(0x3c9, blue & colmask);
- DACDelay;
- return 0;
-
- case IS_MV300:
- OUTB((MV300_reg[regno] << 2) + 1, red);
- OUTB((MV300_reg[regno] << 2) + 1, green);
- OUTB((MV300_reg[regno] << 2) + 1, blue);
- return 0;
-
- default:
- return 1;
- }
-}
-
-static int ext_detect(void)
-{
- struct fb_var_screeninfo *myvar = &atafb_predefined[0];
- struct atafb_par dummy_par;
-
- myvar->xres = external_xres;
- myvar->xres_virtual = external_xres_virtual;
- myvar->yres = external_yres;
- myvar->bits_per_pixel = external_depth;
- ext_encode_var(myvar, &dummy_par);
- return 1;
-}
-
-#endif /* ATAFB_EXT */
-
-/* ------ This is the same for most hardware types -------- */
-
-static void set_screen_base(void *s_base)
-{
- unsigned long addr;
-
- addr = atari_stram_to_phys(s_base);
- /* Setup Screen Memory */
- shifter_st.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
- shifter_st.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
- shifter_st.bas_lo = (unsigned char)(addr & 0x0000ff);
-}
-
-static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct atafb_par *par = info->par;
-
- if (!fbhw->set_screen_base ||
- (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
- return -EINVAL;
- var->xoffset = round_up(var->xoffset, 16);
- par->screen_base = screen_base +
- (var->yoffset * info->var.xres_virtual + var->xoffset)
- * info->var.bits_per_pixel / 8;
- fbhw->set_screen_base(par->screen_base);
- return 0;
-}
-
-/* ------------ Interfaces to hardware functions ------------ */
-
-#ifdef ATAFB_TT
-static struct fb_hwswitch tt_switch = {
- .detect = tt_detect,
- .encode_fix = tt_encode_fix,
- .decode_var = tt_decode_var,
- .encode_var = tt_encode_var,
- .get_par = tt_get_par,
- .set_par = tt_set_par,
- .set_screen_base = set_screen_base,
- .pan_display = pan_display,
-};
-#endif
-
-#ifdef ATAFB_FALCON
-static struct fb_hwswitch falcon_switch = {
- .detect = falcon_detect,
- .encode_fix = falcon_encode_fix,
- .decode_var = falcon_decode_var,
- .encode_var = falcon_encode_var,
- .get_par = falcon_get_par,
- .set_par = falcon_set_par,
- .set_screen_base = set_screen_base,
- .blank = falcon_blank,
- .pan_display = falcon_pan_display,
-};
-#endif
-
-#ifdef ATAFB_STE
-static struct fb_hwswitch st_switch = {
- .detect = stste_detect,
- .encode_fix = stste_encode_fix,
- .decode_var = stste_decode_var,
- .encode_var = stste_encode_var,
- .get_par = stste_get_par,
- .set_par = stste_set_par,
- .set_screen_base = stste_set_screen_base,
- .pan_display = pan_display
-};
-#endif
-
-#ifdef ATAFB_EXT
-static struct fb_hwswitch ext_switch = {
- .detect = ext_detect,
- .encode_fix = ext_encode_fix,
- .decode_var = ext_decode_var,
- .encode_var = ext_encode_var,
- .get_par = ext_get_par,
- .set_par = ext_set_par,
-};
-#endif
-
-static void ata_get_par(struct atafb_par *par)
-{
- if (current_par_valid)
- *par = current_par;
- else
- fbhw->get_par(par);
-}
-
-static void ata_set_par(struct atafb_par *par)
-{
- fbhw->set_par(par);
- current_par = *par;
- current_par_valid = 1;
-}
-
-
-/* =========================================================== */
-/* ============== Hardware Independent Functions ============= */
-/* =========================================================== */
-
-/* used for hardware scrolling */
-
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
- int err, activate;
- struct atafb_par par;
-
- err = fbhw->decode_var(var, &par);
- if (err)
- return err;
- activate = var->activate;
- if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
- ata_set_par(&par);
- fbhw->encode_var(var, &par);
- var->activate = activate;
- return 0;
-}
-
-/* fbhw->encode_fix() must be called with fb_info->mm_lock held
- * if it is called after the register_framebuffer() - not a case here
- */
-static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
-{
- struct atafb_par par;
- int err;
- // Get fix directly (case con == -1 before)??
- err = fbhw->decode_var(&info->var, &par);
- if (err)
- return err;
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- err = fbhw->encode_fix(fix, &par);
- return err;
-}
-
-static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct atafb_par par;
-
- ata_get_par(&par);
- fbhw->encode_var(var, &par);
-
- return 0;
-}
-
-// No longer called by fbcon!
-// Still called by set_var internally
-
-static void atafb_set_disp(struct fb_info *info)
-{
- atafb_get_var(&info->var, info);
- atafb_get_fix(&info->fix, info);
-
- /* Note: smem_start derives from phys_screen_base, not screen_base! */
- info->screen_base = (external_addr ? external_screen_base :
- atari_stram_to_virt(info->fix.smem_start));
-}
-
-static int
-atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- if (!fbhw->pan_display)
- return -EINVAL;
-
- return fbhw->pan_display(var, info);
-}
-
-/*
- * generic drawing routines; imageblit needs updating for image depth > 1
- */
-
-static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- struct atafb_par *par = info->par;
- int x2, y2;
- u32 width, height;
-
- if (!rect->width || !rect->height)
- return;
-
-#ifdef ATAFB_FALCON
- if (info->var.bits_per_pixel == 16) {
- cfb_fillrect(info, rect);
- return;
- }
-#endif
-
- /*
- * We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly.
- * */
- x2 = rect->dx + rect->width;
- y2 = rect->dy + rect->height;
- x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
- y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
- width = x2 - rect->dx;
- height = y2 - rect->dy;
-
- if (info->var.bits_per_pixel == 1)
- atafb_mfb_fillrect(info, par->next_line, rect->color,
- rect->dy, rect->dx, height, width);
- else if (info->var.bits_per_pixel == 2)
- atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
- rect->dy, rect->dx, height, width);
- else if (info->var.bits_per_pixel == 4)
- atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
- rect->dy, rect->dx, height, width);
- else
- atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
- rect->dy, rect->dx, height, width);
-
- return;
-}
-
-static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
- struct atafb_par *par = info->par;
- int x2, y2;
- u32 dx, dy, sx, sy, width, height;
- int rev_copy = 0;
-
-#ifdef ATAFB_FALCON
- if (info->var.bits_per_pixel == 16) {
- cfb_copyarea(info, area);
- return;
- }
-#endif
-
- /* clip the destination */
- x2 = area->dx + area->width;
- y2 = area->dy + area->height;
- dx = area->dx > 0 ? area->dx : 0;
- dy = area->dy > 0 ? area->dy : 0;
- x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
- y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
- width = x2 - dx;
- height = y2 - dy;
-
- if (area->sx + dx < area->dx || area->sy + dy < area->dy)
- return;
-
- /* update sx,sy */
- sx = area->sx + (dx - area->dx);
- sy = area->sy + (dy - area->dy);
-
- /* the source must be completely inside the virtual screen */
- if (sx + width > info->var.xres_virtual ||
- sy + height > info->var.yres_virtual)
- return;
-
- if (dy > sy || (dy == sy && dx > sx)) {
- dy += height;
- sy += height;
- rev_copy = 1;
- }
-
- if (info->var.bits_per_pixel == 1)
- atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
- else if (info->var.bits_per_pixel == 2)
- atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
- else if (info->var.bits_per_pixel == 4)
- atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
- else
- atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
-
- return;
-}
-
-static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- struct atafb_par *par = info->par;
- int x2, y2;
- const char *src;
- u32 dx, dy, width, height, pitch;
-
-#ifdef ATAFB_FALCON
- if (info->var.bits_per_pixel == 16) {
- cfb_imageblit(info, image);
- return;
- }
-#endif
-
- /*
- * We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly like we are
- * doing here.
- */
- x2 = image->dx + image->width;
- y2 = image->dy + image->height;
- dx = image->dx;
- dy = image->dy;
- x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
- y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
- width = x2 - dx;
- height = y2 - dy;
-
- if (image->depth == 1) {
- // used for font data
- src = image->data;
- pitch = (image->width + 7) / 8;
- while (height--) {
-
- if (info->var.bits_per_pixel == 1)
- atafb_mfb_linefill(info, par->next_line,
- dy, dx, width, src,
- image->bg_color, image->fg_color);
- else if (info->var.bits_per_pixel == 2)
- atafb_iplan2p2_linefill(info, par->next_line,
- dy, dx, width, src,
- image->bg_color, image->fg_color);
- else if (info->var.bits_per_pixel == 4)
- atafb_iplan2p4_linefill(info, par->next_line,
- dy, dx, width, src,
- image->bg_color, image->fg_color);
- else
- atafb_iplan2p8_linefill(info, par->next_line,
- dy, dx, width, src,
- image->bg_color, image->fg_color);
- dy++;
- src += pitch;
- }
- } else {
- c2p_iplan2(info->screen_base, image->data, dx, dy, width,
- height, par->next_line, image->width,
- info->var.bits_per_pixel);
- }
-}
-
-static int
-atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
-#ifdef FBCMD_GET_CURRENTPAR
- case FBCMD_GET_CURRENTPAR:
- if (copy_to_user((void *)arg, ¤t_par,
- sizeof(struct atafb_par)))
- return -EFAULT;
- return 0;
-#endif
-#ifdef FBCMD_SET_CURRENTPAR
- case FBCMD_SET_CURRENTPAR:
- if (copy_from_user(¤t_par, (void *)arg,
- sizeof(struct atafb_par)))
- return -EFAULT;
- ata_set_par(¤t_par);
- return 0;
-#endif
- }
- return -EINVAL;
-}
-
-/* (un)blank/poweroff
- * 0 = unblank
- * 1 = blank
- * 2 = suspend vsync
- * 3 = suspend hsync
- * 4 = off
- */
-static int atafb_blank(int blank, struct fb_info *info)
-{
- unsigned short black[16];
- struct fb_cmap cmap;
- if (fbhw->blank && !fbhw->blank(blank))
- return 1;
- if (blank) {
- memset(black, 0, 16 * sizeof(unsigned short));
- cmap.red = black;
- cmap.green = black;
- cmap.blue = black;
- cmap.transp = NULL;
- cmap.start = 0;
- cmap.len = 16;
- fb_set_cmap(&cmap, info);
- }
-#if 0
- else
- do_install_cmap(info);
-#endif
- return 0;
-}
-
- /*
- * New fbcon interface ...
- */
-
- /* check var by decoding var into hw par, rounding if necessary,
- * then encoding hw par back into new, validated var */
-static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- int err;
- struct atafb_par par;
-
- /* Validate wanted screen parameters */
- // if ((err = ata_decode_var(var, &par)))
- err = fbhw->decode_var(var, &par);
- if (err)
- return err;
-
- /* Encode (possibly rounded) screen parameters */
- fbhw->encode_var(var, &par);
- return 0;
-}
-
- /* actually set hw par by decoding var, then setting hardware from
- * hw par just decoded */
-static int atafb_set_par(struct fb_info *info)
-{
- struct atafb_par *par = info->par;
-
- /* Decode wanted screen parameters */
- fbhw->decode_var(&info->var, par);
- mutex_lock(&info->mm_lock);
- fbhw->encode_fix(&info->fix, par);
- mutex_unlock(&info->mm_lock);
-
- /* Set new videomode */
- ata_set_par(par);
-
- return 0;
-}
-
-
-static struct fb_ops atafb_ops = {
- .owner = THIS_MODULE,
- __FB_DEFAULT_IOMEM_OPS_RDWR,
- .fb_check_var = atafb_check_var,
- .fb_set_par = atafb_set_par,
- .fb_blank = atafb_blank,
- .fb_pan_display = atafb_pan_display,
- .fb_fillrect = atafb_fillrect,
- .fb_copyarea = atafb_copyarea,
- .fb_imageblit = atafb_imageblit,
- .fb_ioctl = atafb_ioctl,
- __FB_DEFAULT_IOMEM_OPS_MMAP,
-};
-
-static void check_default_par(int detected_mode)
-{
- char default_name[10];
- int i;
- struct fb_var_screeninfo var;
- unsigned long min_mem;
-
- /* First try the user supplied mode */
- if (default_par) {
- var = atafb_predefined[default_par - 1];
- var.activate = FB_ACTIVATE_TEST;
- if (do_fb_set_var(&var, 1))
- default_par = 0; /* failed */
- }
- /* Next is the autodetected one */
- if (!default_par) {
- var = atafb_predefined[detected_mode - 1]; /* autodetect */
- var.activate = FB_ACTIVATE_TEST;
- if (!do_fb_set_var(&var, 1))
- default_par = detected_mode;
- }
- /* If that also failed, try some default modes... */
- if (!default_par) {
- /* try default1, default2... */
- for (i = 1; i < 10; i++) {
- sprintf(default_name,"default%d", i);
- default_par = get_video_mode(default_name);
- if (!default_par)
- panic("can't set default video mode");
- var = atafb_predefined[default_par - 1];
- var.activate = FB_ACTIVATE_TEST;
- if (!do_fb_set_var(&var,1))
- break; /* ok */
- }
- }
- min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
- if (default_mem_req < min_mem)
- default_mem_req = min_mem;
-}
-
-#ifdef ATAFB_EXT
-static void __init atafb_setup_ext(char *spec)
-{
- int xres, xres_virtual, yres, depth, planes;
- unsigned long addr, len;
- char *p;
-
- /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
- * <screen mem addr>
- * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
- * [;<xres-virtual>]]]]]
- *
- * 09/23/97 Juergen
- * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
- *
- * Even xres_virtual is available, we neither support panning nor hw-scrolling!
- */
- p = strsep(&spec, ";");
- if (!p || !*p)
- return;
- xres_virtual = xres = simple_strtoul(p, NULL, 10);
- if (xres <= 0)
- return;
-
- p = strsep(&spec, ";");
- if (!p || !*p)
- return;
- yres = simple_strtoul(p, NULL, 10);
- if (yres <= 0)
- return;
-
- p = strsep(&spec, ";");
- if (!p || !*p)
- return;
- depth = simple_strtoul(p, NULL, 10);
- if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
- depth != 16 && depth != 24)
- return;
-
- p = strsep(&spec, ";");
- if (!p || !*p)
- return;
- if (*p == 'i')
- planes = FB_TYPE_INTERLEAVED_PLANES;
- else if (*p == 'p')
- planes = FB_TYPE_PACKED_PIXELS;
- else if (*p == 'n')
- planes = FB_TYPE_PLANES;
- else if (*p == 't')
- planes = -1; /* true color */
- else
- return;
-
- p = strsep(&spec, ";");
- if (!p || !*p)
- return;
- addr = simple_strtoul(p, NULL, 0);
-
- p = strsep(&spec, ";");
- if (!p || !*p)
- len = xres * yres * depth / 8;
- else
- len = simple_strtoul(p, NULL, 0);
-
- p = strsep(&spec, ";");
- if (p && *p)
- external_vgaiobase = simple_strtoul(p, NULL, 0);
-
- p = strsep(&spec, ";");
- if (p && *p) {
- external_bitspercol = simple_strtoul(p, NULL, 0);
- if (external_bitspercol > 8)
- external_bitspercol = 8;
- else if (external_bitspercol < 1)
- external_bitspercol = 1;
- }
-
- p = strsep(&spec, ";");
- if (p && *p) {
- if (!strcmp(p, "vga"))
- external_card_type = IS_VGA;
- if (!strcmp(p, "mv300"))
- external_card_type = IS_MV300;
- }
-
- p = strsep(&spec, ";");
- if (p && *p) {
- xres_virtual = simple_strtoul(p, NULL, 10);
- if (xres_virtual < xres)
- xres_virtual = xres;
- if (xres_virtual * yres * depth / 8 > len)
- len = xres_virtual * yres * depth / 8;
- }
-
- external_xres = xres;
- external_xres_virtual = xres_virtual;
- external_yres = yres;
- external_depth = depth;
- external_pmode = planes;
- external_addr = addr;
- external_len = len;
-
- if (external_card_type == IS_MV300) {
- switch (external_depth) {
- case 1:
- MV300_reg = MV300_reg_1bit;
- break;
- case 4:
- MV300_reg = MV300_reg_4bit;
- break;
- case 8:
- MV300_reg = MV300_reg_8bit;
- break;
- }
- }
-}
-#endif /* ATAFB_EXT */
-
-static void __init atafb_setup_int(char *spec)
-{
- /* Format to config extended internal video hardware like OverScan:
- * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
- * Explanation:
- * <xres>: x-resolution
- * <yres>: y-resolution
- * The following are only needed if you have an overscan which
- * needs a black border:
- * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
- * <yres_max>: max. number of lines your OverScan hardware would allow
- * <offset>: Offset from physical beginning to visible beginning
- * of screen in bytes
- */
- int xres;
- char *p;
-
- if (!(p = strsep(&spec, ";")) || !*p)
- return;
- xres = simple_strtoul(p, NULL, 10);
- if (!(p = strsep(&spec, ";")) || !*p)
- return;
- sttt_xres = xres;
- tt_yres = st_yres = simple_strtoul(p, NULL, 10);
- if ((p = strsep(&spec, ";")) && *p)
- sttt_xres_virtual = simple_strtoul(p, NULL, 10);
- if ((p = strsep(&spec, ";")) && *p)
- sttt_yres_virtual = simple_strtoul(p, NULL, 0);
- if ((p = strsep(&spec, ";")) && *p)
- ovsc_offset = simple_strtoul(p, NULL, 0);
-
- if (ovsc_offset || (sttt_yres_virtual != st_yres))
- use_hwscroll = 0;
-}
-
-#ifdef ATAFB_FALCON
-static void __init atafb_setup_mcap(char *spec)
-{
- char *p;
- int vmin, vmax, hmin, hmax;
-
- /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
- * <V*> vertical freq. in Hz
- * <H*> horizontal freq. in kHz
- */
- if (!(p = strsep(&spec, ";")) || !*p)
- return;
- vmin = simple_strtoul(p, NULL, 10);
- if (vmin <= 0)
- return;
- if (!(p = strsep(&spec, ";")) || !*p)
- return;
- vmax = simple_strtoul(p, NULL, 10);
- if (vmax <= 0 || vmax <= vmin)
- return;
- if (!(p = strsep(&spec, ";")) || !*p)
- return;
- hmin = 1000 * simple_strtoul(p, NULL, 10);
- if (hmin <= 0)
- return;
- if (!(p = strsep(&spec, "")) || !*p)
- return;
- hmax = 1000 * simple_strtoul(p, NULL, 10);
- if (hmax <= 0 || hmax <= hmin)
- return;
-
- fb_info.monspecs.vfmin = vmin;
- fb_info.monspecs.vfmax = vmax;
- fb_info.monspecs.hfmin = hmin;
- fb_info.monspecs.hfmax = hmax;
-}
-#endif /* ATAFB_FALCON */
-
-static void __init atafb_setup_user(char *spec)
-{
- /* Format of user defined video mode is: <xres>;<yres>;<depth>
- */
- char *p;
- int xres, yres, depth, temp;
-
- p = strsep(&spec, ";");
- if (!p || !*p)
- return;
- xres = simple_strtoul(p, NULL, 10);
- p = strsep(&spec, ";");
- if (!p || !*p)
- return;
- yres = simple_strtoul(p, NULL, 10);
- p = strsep(&spec, "");
- if (!p || !*p)
- return;
- depth = simple_strtoul(p, NULL, 10);
- temp = get_video_mode("user0");
- if (temp) {
- default_par = temp;
- atafb_predefined[default_par - 1].xres = xres;
- atafb_predefined[default_par - 1].yres = yres;
- atafb_predefined[default_par - 1].bits_per_pixel = depth;
- }
-}
-
-static int __init atafb_setup(char *options)
-{
- char *this_opt;
- int temp;
-
- if (!options || !*options)
- return 0;
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!*this_opt)
- continue;
- if ((temp = get_video_mode(this_opt))) {
- default_par = temp;
- mode_option = this_opt;
- } else if (!strcmp(this_opt, "inverse"))
- fb_invert_cmaps();
- else if (!strncmp(this_opt, "hwscroll_", 9)) {
- hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
- if (hwscroll < 0)
- hwscroll = 0;
- if (hwscroll > 200)
- hwscroll = 200;
- }
-#ifdef ATAFB_EXT
- else if (!strcmp(this_opt, "mv300")) {
- external_bitspercol = 8;
- external_card_type = IS_MV300;
- } else if (!strncmp(this_opt, "external:", 9))
- atafb_setup_ext(this_opt + 9);
-#endif
- else if (!strncmp(this_opt, "internal:", 9))
- atafb_setup_int(this_opt + 9);
-#ifdef ATAFB_FALCON
- else if (!strncmp(this_opt, "eclock:", 7)) {
- fext.f = simple_strtoul(this_opt + 7, NULL, 10);
- /* external pixelclock in kHz --> ps */
- fext.t = 1000000000 / fext.f;
- fext.f *= 1000;
- } else if (!strncmp(this_opt, "monitorcap:", 11))
- atafb_setup_mcap(this_opt + 11);
-#endif
- else if (!strcmp(this_opt, "keep"))
- DontCalcRes = 1;
- else if (!strncmp(this_opt, "R", 1))
- atafb_setup_user(this_opt + 1);
- }
- return 0;
-}
-
-static int __init atafb_probe(struct platform_device *pdev)
-{
- int pad, detected_mode, error;
- unsigned int defmode = 0;
- unsigned long mem_req;
- char *option = NULL;
-
- if (fb_get_options("atafb", &option))
- return -ENODEV;
- atafb_setup(option);
- dev_dbg(&pdev->dev, "%s: start\n", __func__);
-
- do {
-#ifdef ATAFB_EXT
- if (external_addr) {
- dev_dbg(&pdev->dev, "initializing external hw\n");
- fbhw = &ext_switch;
- atafb_ops.fb_setcolreg = &ext_setcolreg;
- defmode = DEFMODE_EXT;
- break;
- }
-#endif
-#ifdef ATAFB_TT
- if (ATARIHW_PRESENT(TT_SHIFTER)) {
- dev_dbg(&pdev->dev, "initializing TT hw\n");
- fbhw = &tt_switch;
- atafb_ops.fb_setcolreg = &tt_setcolreg;
- defmode = DEFMODE_TT;
- break;
- }
-#endif
-#ifdef ATAFB_FALCON
- if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
- dev_dbg(&pdev->dev, "initializing Falcon hw\n");
- fbhw = &falcon_switch;
- atafb_ops.fb_setcolreg = &falcon_setcolreg;
- error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
- "framebuffer:modeswitch",
- falcon_vbl_switcher);
- if (error)
- return error;
- defmode = DEFMODE_F30;
- break;
- }
-#endif
-#ifdef ATAFB_STE
- if (ATARIHW_PRESENT(STND_SHIFTER) ||
- ATARIHW_PRESENT(EXTD_SHIFTER)) {
- dev_dbg(&pdev->dev, "initializing ST/E hw\n");
- fbhw = &st_switch;
- atafb_ops.fb_setcolreg = &stste_setcolreg;
- defmode = DEFMODE_STE;
- break;
- }
- fbhw = &st_switch;
- atafb_ops.fb_setcolreg = &stste_setcolreg;
- dev_warn(&pdev->dev,
- "Cannot determine video hardware; defaulting to ST(e)\n");
-#else /* ATAFB_STE */
- /* no default driver included */
- /* Nobody will ever see this message :-) */
- panic("Cannot initialize video hardware");
-#endif
- } while (0);
-
- /* Multisync monitor capabilities */
- /* Atari-TOS defaults if no boot option present */
- if (fb_info.monspecs.hfmin == 0) {
- fb_info.monspecs.hfmin = 31000;
- fb_info.monspecs.hfmax = 32000;
- fb_info.monspecs.vfmin = 58;
- fb_info.monspecs.vfmax = 62;
- }
-
- detected_mode = fbhw->detect();
- check_default_par(detected_mode);
-#ifdef ATAFB_EXT
- if (!external_addr) {
-#endif /* ATAFB_EXT */
- mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
- mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
- screen_base = atari_stram_alloc(mem_req, "atafb");
- if (!screen_base)
- panic("Cannot allocate screen memory");
- memset(screen_base, 0, mem_req);
- pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
- screen_base += pad;
- phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
- screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
- st_ovsc_switch();
- if (CPU_IS_040_OR_060) {
- /* On a '040+, the cache mode of video RAM must be set to
- * write-through also for internal video hardware! */
- cache_push(atari_stram_to_phys(screen_base), screen_len);
- kernel_set_cachemode(screen_base, screen_len,
- IOMAP_WRITETHROUGH);
- }
- dev_info(&pdev->dev, "phys_screen_base %lx screen_len %d\n",
- phys_screen_base, screen_len);
-#ifdef ATAFB_EXT
- } else {
- /* Map the video memory (physical address given) to somewhere
- * in the kernel address space.
- */
- external_screen_base = ioremap_wt(external_addr, external_len);
- if (external_vgaiobase)
- external_vgaiobase =
- (unsigned long)ioremap(external_vgaiobase, 0x10000);
- screen_base = external_screen_base;
- phys_screen_base = external_addr;
- screen_len = external_len & PAGE_MASK;
- memset (screen_base, 0, external_len);
- }
-#endif /* ATAFB_EXT */
-
-// strcpy(fb_info.mode->name, "Atari Builtin ");
- fb_info.fbops = &atafb_ops;
- // try to set default (detected; requested) var
- do_fb_set_var(&atafb_predefined[default_par - 1], 1);
- // reads hw state into current par, which may not be sane yet
- ata_get_par(¤t_par);
- fb_info.par = ¤t_par;
- // tries to read from HW which may not be initialized yet
- // so set sane var first, then call atafb_set_par
- atafb_get_var(&fb_info.var, &fb_info);
-
-#ifdef ATAFB_FALCON
- fb_info.pseudo_palette = current_par.hw.falcon.pseudo_palette;
-#endif
-
- if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
- NUM_TOTAL_MODES, &atafb_modedb[defmode],
- fb_info.var.bits_per_pixel)) {
- return -EINVAL;
- }
-
- fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
- &fb_info.modelist);
-
- atafb_set_disp(&fb_info);
-
- fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
-
-
- dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
- fb_info.var.yres, fb_info.var.bits_per_pixel);
- if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
- (fb_info.var.yres != fb_info.var.yres_virtual))
- dev_info(&pdev->dev, " virtual %dx%d\n",
- fb_info.var.xres_virtual, fb_info.var.yres_virtual);
-
- if (register_framebuffer(&fb_info) < 0) {
-#ifdef ATAFB_EXT
- if (external_addr) {
- iounmap(external_screen_base);
- external_addr = 0;
- }
- if (external_vgaiobase) {
- iounmap((void*)external_vgaiobase);
- external_vgaiobase = 0;
- }
-#endif
- return -EINVAL;
- }
-
- fb_info(&fb_info, "frame buffer device, using %dK of video memory\n",
- screen_len >> 10);
-
- /* TODO: This driver cannot be unloaded yet */
- return 0;
-}
-
-static void atafb_shutdown(struct platform_device *pdev)
-{
- /* Unblank before kexec */
- if (fbhw->blank)
- fbhw->blank(0);
-}
-
-static struct platform_driver atafb_driver = {
- .shutdown = atafb_shutdown,
- .driver = {
- .name = "atafb",
- },
-};
-
-static int __init atafb_init(void)
-{
- struct platform_device *pdev;
-
- if (!MACH_IS_ATARI)
- return -ENODEV;
-
- pdev = platform_device_register_simple("atafb", -1, NULL, 0);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- return platform_driver_probe(&atafb_driver, atafb_probe);
-}
-
-device_initcall(atafb_init);
diff --git a/drivers/video/fbdev/atafb.h b/drivers/video/fbdev/atafb.h
deleted file mode 100644
index 2b2675980..000000000
--- a/drivers/video/fbdev/atafb.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VIDEO_ATAFB_H
-#define _VIDEO_ATAFB_H
-
-void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
- int dx, int height, int width);
-void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
- int sy, int sx, int height, int width);
-void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
- int dy, int dx, u32 width,
- const u8 *data, u32 bgcolor, u32 fgcolor);
-
-void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
- int dx, int height, int width);
-void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
- int sy, int sx, int height, int width);
-void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
- int dy, int dx, u32 width,
- const u8 *data, u32 bgcolor, u32 fgcolor);
-
-void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
- int dx, int height, int width);
-void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
- int sy, int sx, int height, int width);
-void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
- int dy, int dx, u32 width,
- const u8 *data, u32 bgcolor, u32 fgcolor);
-
-void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
- int dx, int height, int width);
-void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
- int sy, int sx, int height, int width);
-void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
- int dy, int dx, u32 width,
- const u8 *data, u32 bgcolor, u32 fgcolor);
-
-#endif /* _VIDEO_ATAFB_H */
diff --git a/drivers/video/fbdev/atafb_iplan2p2.c b/drivers/video/fbdev/atafb_iplan2p2.c
deleted file mode 100644
index a1660c24b..000000000
--- a/drivers/video/fbdev/atafb_iplan2p2.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for
- * interleaved bitplanes à la Atari (2
- * planes, 2 bytes interleave)
- *
- * Created 5 Apr 1997 by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include <asm/setup.h>
-
-#include "atafb.h"
-
-#define BPL 2
-#include "atafb_utils.h"
-
-void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line,
- int sy, int sx, int dy, int dx,
- int height, int width)
-{
- /* bmove() has to distinguish two major cases: If both, source and
- * destination, start at even addresses or both are at odd
- * addresses, just the first odd and last even column (if present)
- * require special treatment (memmove_col()). The rest between
- * then can be copied by normal operations, because all adjacent
- * bytes are affected and are to be stored in the same order.
- * The pathological case is when the move should go from an odd
- * address to an even or vice versa. Since the bytes in the plane
- * words must be assembled in new order, it seems wisest to make
- * all movements by memmove_col().
- */
-
- u8 *src, *dst;
- u32 *s, *d;
- int w, l , i, j;
- u_int colsize;
- u_int upwards = (dy < sy) || (dy == sy && dx < sx);
-
- colsize = height;
- if (!((sx ^ dx) & 15)) {
- /* odd->odd or even->even */
-
- if (upwards) {
- src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
- if (sx & 15) {
- memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
- src += BPL * 2;
- dst += BPL * 2;
- width -= 8;
- }
- w = width >> 4;
- if (w) {
- s = (u32 *)src;
- d = (u32 *)dst;
- w *= BPL / 2;
- l = next_line - w * 4;
- for (j = height; j > 0; j--) {
- for (i = w; i > 0; i--)
- *d++ = *s++;
- s = (u32 *)((u8 *)s + l);
- d = (u32 *)((u8 *)d + l);
- }
- }
- if (width & 15)
- memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
- 0xff00ff00, height, next_line - BPL * 2);
- } else {
- src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
- if ((sx + width) & 15) {
- src -= BPL * 2;
- dst -= BPL * 2;
- memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
- width -= 8;
- }
- w = width >> 4;
- if (w) {
- s = (u32 *)src;
- d = (u32 *)dst;
- w *= BPL / 2;
- l = next_line - w * 4;
- for (j = height; j > 0; j--) {
- for (i = w; i > 0; i--)
- *--d = *--s;
- s = (u32 *)((u8 *)s - l);
- d = (u32 *)((u8 *)d - l);
- }
- }
- if (sx & 15)
- memmove32_col(dst - (width - 16) / (8 / BPL),
- src - (width - 16) / (8 / BPL),
- 0xff00ff, colsize, -next_line - BPL * 2);
- }
- } else {
- /* odd->even or even->odd */
- if (upwards) {
- u32 *src32, *dst32;
- u32 pval[4], v, v1, mask;
- int i, j, w, f;
-
- src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-
- mask = 0xff00ff00;
- f = 0;
- w = width;
- if (sx & 15) {
- f = 1;
- w += 8;
- }
- if ((sx + width) & 15)
- f |= 2;
- w >>= 4;
- for (i = height; i; i--) {
- src32 = (u32 *)src;
- dst32 = (u32 *)dst;
-
- if (f & 1) {
- pval[0] = (*src32++ << 8) & mask;
- } else {
- pval[0] = dst32[0] & mask;
- }
-
- for (j = w; j > 0; j--) {
- v = *src32++;
- v1 = v & mask;
- *dst32++ = pval[0] | (v1 >> 8);
- pval[0] = (v ^ v1) << 8;
- }
-
- if (f & 2) {
- dst32[0] = (dst32[0] & mask) | pval[0];
- }
-
- src += next_line;
- dst += next_line;
- }
- } else {
- u32 *src32, *dst32;
- u32 pval[4], v, v1, mask;
- int i, j, w, f;
-
- src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
- mask = 0xff00ff;
- f = 0;
- w = width;
- if ((dx + width) & 15)
- f = 1;
- if (sx & 15) {
- f |= 2;
- w += 8;
- }
- w >>= 4;
- for (i = height; i; i--) {
- src32 = (u32 *)src;
- dst32 = (u32 *)dst;
-
- if (f & 1) {
- pval[0] = dst32[-1] & mask;
- } else {
- pval[0] = (*--src32 >> 8) & mask;
- }
-
- for (j = w; j > 0; j--) {
- v = *--src32;
- v1 = v & mask;
- *--dst32 = pval[0] | (v1 << 8);
- pval[0] = (v ^ v1) >> 8;
- }
-
- if (!(f & 2)) {
- dst32[-1] = (dst32[-1] & mask) | pval[0];
- }
-
- src -= next_line;
- dst -= next_line;
- }
- }
- }
-}
-
-void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
- int sy, int sx, int height, int width)
-{
- u32 *dest;
- int rows, i;
- u32 cval[4];
-
- dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
- if (sx & 15) {
- u8 *dest8 = (u8 *)dest + 1;
-
- expand8_col2mask(color, cval);
-
- for (i = height; i; i--) {
- fill8_col(dest8, cval);
- dest8 += next_line;
- }
- dest += BPL / 2;
- width -= 8;
- }
-
- expand16_col2mask(color, cval);
- rows = width >> 4;
- if (rows) {
- u32 *d = dest;
- u32 off = next_line - rows * BPL * 2;
- for (i = height; i; i--) {
- d = fill16_col(d, rows, cval);
- d = (u32 *)((long)d + off);
- }
- dest += rows * BPL / 2;
- width &= 15;
- }
-
- if (width) {
- u8 *dest8 = (u8 *)dest;
-
- expand8_col2mask(color, cval);
-
- for (i = height; i; i--) {
- fill8_col(dest8, cval);
- dest8 += next_line;
- }
- }
-}
-
-void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
- int dy, int dx, u32 width,
- const u8 *data, u32 bgcolor, u32 fgcolor)
-{
- u32 *dest;
- const u16 *data16;
- int rows;
- u32 fgm[4], bgm[4], m;
-
- dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
- if (dx & 15) {
- fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
- dest += BPL / 2;
- width -= 8;
- }
-
- if (width >= 16) {
- data16 = (const u16 *)data;
- expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
-
- for (rows = width / 16; rows; rows--) {
- u16 d = *data16++;
- m = d | ((u32)d << 16);
- *dest++ = (m & fgm[0]) ^ bgm[0];
- }
-
- data = (const u8 *)data16;
- width &= 15;
- }
-
- if (width)
- fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
-}
diff --git a/drivers/video/fbdev/atafb_iplan2p4.c b/drivers/video/fbdev/atafb_iplan2p4.c
deleted file mode 100644
index 663d66582..000000000
--- a/drivers/video/fbdev/atafb_iplan2p4.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for
- * interleaved bitplanes à la Atari (4
- * planes, 2 bytes interleave)
- *
- * Created 5 Apr 1997 by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include <asm/setup.h>
-
-#include "atafb.h"
-
-#define BPL 4
-#include "atafb_utils.h"
-
-void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line,
- int sy, int sx, int dy, int dx,
- int height, int width)
-{
- /* bmove() has to distinguish two major cases: If both, source and
- * destination, start at even addresses or both are at odd
- * addresses, just the first odd and last even column (if present)
- * require special treatment (memmove_col()). The rest between
- * then can be copied by normal operations, because all adjacent
- * bytes are affected and are to be stored in the same order.
- * The pathological case is when the move should go from an odd
- * address to an even or vice versa. Since the bytes in the plane
- * words must be assembled in new order, it seems wisest to make
- * all movements by memmove_col().
- */
-
- u8 *src, *dst;
- u32 *s, *d;
- int w, l , i, j;
- u_int colsize;
- u_int upwards = (dy < sy) || (dy == sy && dx < sx);
-
- colsize = height;
- if (!((sx ^ dx) & 15)) {
- /* odd->odd or even->even */
-
- if (upwards) {
- src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
- if (sx & 15) {
- memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
- src += BPL * 2;
- dst += BPL * 2;
- width -= 8;
- }
- w = width >> 4;
- if (w) {
- s = (u32 *)src;
- d = (u32 *)dst;
- w *= BPL / 2;
- l = next_line - w * 4;
- for (j = height; j > 0; j--) {
- for (i = w; i > 0; i--)
- *d++ = *s++;
- s = (u32 *)((u8 *)s + l);
- d = (u32 *)((u8 *)d + l);
- }
- }
- if (width & 15)
- memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
- 0xff00ff00, height, next_line - BPL * 2);
- } else {
- src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
- if ((sx + width) & 15) {
- src -= BPL * 2;
- dst -= BPL * 2;
- memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
- width -= 8;
- }
- w = width >> 4;
- if (w) {
- s = (u32 *)src;
- d = (u32 *)dst;
- w *= BPL / 2;
- l = next_line - w * 4;
- for (j = height; j > 0; j--) {
- for (i = w; i > 0; i--)
- *--d = *--s;
- s = (u32 *)((u8 *)s - l);
- d = (u32 *)((u8 *)d - l);
- }
- }
- if (sx & 15)
- memmove32_col(dst - (width - 16) / (8 / BPL),
- src - (width - 16) / (8 / BPL),
- 0xff00ff, colsize, -next_line - BPL * 2);
- }
- } else {
- /* odd->even or even->odd */
- if (upwards) {
- u32 *src32, *dst32;
- u32 pval[4], v, v1, mask;
- int i, j, w, f;
-
- src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-
- mask = 0xff00ff00;
- f = 0;
- w = width;
- if (sx & 15) {
- f = 1;
- w += 8;
- }
- if ((sx + width) & 15)
- f |= 2;
- w >>= 4;
- for (i = height; i; i--) {
- src32 = (u32 *)src;
- dst32 = (u32 *)dst;
-
- if (f & 1) {
- pval[0] = (*src32++ << 8) & mask;
- pval[1] = (*src32++ << 8) & mask;
- } else {
- pval[0] = dst32[0] & mask;
- pval[1] = dst32[1] & mask;
- }
-
- for (j = w; j > 0; j--) {
- v = *src32++;
- v1 = v & mask;
- *dst32++ = pval[0] | (v1 >> 8);
- pval[0] = (v ^ v1) << 8;
- v = *src32++;
- v1 = v & mask;
- *dst32++ = pval[1] | (v1 >> 8);
- pval[1] = (v ^ v1) << 8;
- }
-
- if (f & 2) {
- dst32[0] = (dst32[0] & mask) | pval[0];
- dst32[1] = (dst32[1] & mask) | pval[1];
- }
-
- src += next_line;
- dst += next_line;
- }
- } else {
- u32 *src32, *dst32;
- u32 pval[4], v, v1, mask;
- int i, j, w, f;
-
- src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
- mask = 0xff00ff;
- f = 0;
- w = width;
- if ((dx + width) & 15)
- f = 1;
- if (sx & 15) {
- f |= 2;
- w += 8;
- }
- w >>= 4;
- for (i = height; i; i--) {
- src32 = (u32 *)src;
- dst32 = (u32 *)dst;
-
- if (f & 1) {
- pval[0] = dst32[-1] & mask;
- pval[1] = dst32[-2] & mask;
- } else {
- pval[0] = (*--src32 >> 8) & mask;
- pval[1] = (*--src32 >> 8) & mask;
- }
-
- for (j = w; j > 0; j--) {
- v = *--src32;
- v1 = v & mask;
- *--dst32 = pval[0] | (v1 << 8);
- pval[0] = (v ^ v1) >> 8;
- v = *--src32;
- v1 = v & mask;
- *--dst32 = pval[1] | (v1 << 8);
- pval[1] = (v ^ v1) >> 8;
- }
-
- if (!(f & 2)) {
- dst32[-1] = (dst32[-1] & mask) | pval[0];
- dst32[-2] = (dst32[-2] & mask) | pval[1];
- }
-
- src -= next_line;
- dst -= next_line;
- }
- }
- }
-}
-
-void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
- int sy, int sx, int height, int width)
-{
- u32 *dest;
- int rows, i;
- u32 cval[4];
-
- dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
- if (sx & 15) {
- u8 *dest8 = (u8 *)dest + 1;
-
- expand8_col2mask(color, cval);
-
- for (i = height; i; i--) {
- fill8_col(dest8, cval);
- dest8 += next_line;
- }
- dest += BPL / 2;
- width -= 8;
- }
-
- expand16_col2mask(color, cval);
- rows = width >> 4;
- if (rows) {
- u32 *d = dest;
- u32 off = next_line - rows * BPL * 2;
- for (i = height; i; i--) {
- d = fill16_col(d, rows, cval);
- d = (u32 *)((long)d + off);
- }
- dest += rows * BPL / 2;
- width &= 15;
- }
-
- if (width) {
- u8 *dest8 = (u8 *)dest;
-
- expand8_col2mask(color, cval);
-
- for (i = height; i; i--) {
- fill8_col(dest8, cval);
- dest8 += next_line;
- }
- }
-}
-
-void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
- int dy, int dx, u32 width,
- const u8 *data, u32 bgcolor, u32 fgcolor)
-{
- u32 *dest;
- const u16 *data16;
- int rows;
- u32 fgm[4], bgm[4], m;
-
- dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
- if (dx & 15) {
- fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
- dest += BPL / 2;
- width -= 8;
- }
-
- if (width >= 16) {
- data16 = (const u16 *)data;
- expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
-
- for (rows = width / 16; rows; rows--) {
- u16 d = *data16++;
- m = d | ((u32)d << 16);
- *dest++ = (m & fgm[0]) ^ bgm[0];
- *dest++ = (m & fgm[1]) ^ bgm[1];
- }
-
- data = (const u8 *)data16;
- width &= 15;
- }
-
- if (width)
- fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
-}
diff --git a/drivers/video/fbdev/atafb_iplan2p8.c b/drivers/video/fbdev/atafb_iplan2p8.c
deleted file mode 100644
index 39a6cbbb6..000000000
--- a/drivers/video/fbdev/atafb_iplan2p8.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for
- * interleaved bitplanes à la Atari (8
- * planes, 2 bytes interleave)
- *
- * Created 5 Apr 1997 by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include <asm/setup.h>
-
-#include "atafb.h"
-
-#define BPL 8
-#include "atafb_utils.h"
-
-
-/* Copies a 8 plane column from 's', height 'h', to 'd'. */
-
-/* This expands a 8 bit color into two longs for two movepl (8 plane)
- * operations.
- */
-
-void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line,
- int sy, int sx, int dy, int dx,
- int height, int width)
-{
- /* bmove() has to distinguish two major cases: If both, source and
- * destination, start at even addresses or both are at odd
- * addresses, just the first odd and last even column (if present)
- * require special treatment (memmove_col()). The rest between
- * then can be copied by normal operations, because all adjacent
- * bytes are affected and are to be stored in the same order.
- * The pathological case is when the move should go from an odd
- * address to an even or vice versa. Since the bytes in the plane
- * words must be assembled in new order, it seems wisest to make
- * all movements by memmove_col().
- */
-
- u8 *src, *dst;
- u32 *s, *d;
- int w, l , i, j;
- u_int colsize;
- u_int upwards = (dy < sy) || (dy == sy && dx < sx);
-
- colsize = height;
- if (!((sx ^ dx) & 15)) {
- /* odd->odd or even->even */
-
- if (upwards) {
- src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
- if (sx & 15) {
- memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
- src += BPL * 2;
- dst += BPL * 2;
- width -= 8;
- }
- w = width >> 4;
- if (w) {
- s = (u32 *)src;
- d = (u32 *)dst;
- w *= BPL / 2;
- l = next_line - w * 4;
- for (j = height; j > 0; j--) {
- for (i = w; i > 0; i--)
- *d++ = *s++;
- s = (u32 *)((u8 *)s + l);
- d = (u32 *)((u8 *)d + l);
- }
- }
- if (width & 15)
- memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
- 0xff00ff00, height, next_line - BPL * 2);
- } else {
- src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
- if ((sx + width) & 15) {
- src -= BPL * 2;
- dst -= BPL * 2;
- memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
- width -= 8;
- }
- w = width >> 4;
- if (w) {
- s = (u32 *)src;
- d = (u32 *)dst;
- w *= BPL / 2;
- l = next_line - w * 4;
- for (j = height; j > 0; j--) {
- for (i = w; i > 0; i--)
- *--d = *--s;
- s = (u32 *)((u8 *)s - l);
- d = (u32 *)((u8 *)d - l);
- }
- }
- if (sx & 15)
- memmove32_col(dst - (width - 16) / (8 / BPL),
- src - (width - 16) / (8 / BPL),
- 0xff00ff, colsize, -next_line - BPL * 2);
- }
- } else {
- /* odd->even or even->odd */
- if (upwards) {
- u32 *src32, *dst32;
- u32 pval[4], v, v1, mask;
- int i, j, w, f;
-
- src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
-
- mask = 0xff00ff00;
- f = 0;
- w = width;
- if (sx & 15) {
- f = 1;
- w += 8;
- }
- if ((sx + width) & 15)
- f |= 2;
- w >>= 4;
- for (i = height; i; i--) {
- src32 = (u32 *)src;
- dst32 = (u32 *)dst;
-
- if (f & 1) {
- pval[0] = (*src32++ << 8) & mask;
- pval[1] = (*src32++ << 8) & mask;
- pval[2] = (*src32++ << 8) & mask;
- pval[3] = (*src32++ << 8) & mask;
- } else {
- pval[0] = dst32[0] & mask;
- pval[1] = dst32[1] & mask;
- pval[2] = dst32[2] & mask;
- pval[3] = dst32[3] & mask;
- }
-
- for (j = w; j > 0; j--) {
- v = *src32++;
- v1 = v & mask;
- *dst32++ = pval[0] | (v1 >> 8);
- pval[0] = (v ^ v1) << 8;
- v = *src32++;
- v1 = v & mask;
- *dst32++ = pval[1] | (v1 >> 8);
- pval[1] = (v ^ v1) << 8;
- v = *src32++;
- v1 = v & mask;
- *dst32++ = pval[2] | (v1 >> 8);
- pval[2] = (v ^ v1) << 8;
- v = *src32++;
- v1 = v & mask;
- *dst32++ = pval[3] | (v1 >> 8);
- pval[3] = (v ^ v1) << 8;
- }
-
- if (f & 2) {
- dst32[0] = (dst32[0] & mask) | pval[0];
- dst32[1] = (dst32[1] & mask) | pval[1];
- dst32[2] = (dst32[2] & mask) | pval[2];
- dst32[3] = (dst32[3] & mask) | pval[3];
- }
-
- src += next_line;
- dst += next_line;
- }
- } else {
- u32 *src32, *dst32;
- u32 pval[4], v, v1, mask;
- int i, j, w, f;
-
- src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
- dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
-
- mask = 0xff00ff;
- f = 0;
- w = width;
- if ((dx + width) & 15)
- f = 1;
- if (sx & 15) {
- f |= 2;
- w += 8;
- }
- w >>= 4;
- for (i = height; i; i--) {
- src32 = (u32 *)src;
- dst32 = (u32 *)dst;
-
- if (f & 1) {
- pval[0] = dst32[-1] & mask;
- pval[1] = dst32[-2] & mask;
- pval[2] = dst32[-3] & mask;
- pval[3] = dst32[-4] & mask;
- } else {
- pval[0] = (*--src32 >> 8) & mask;
- pval[1] = (*--src32 >> 8) & mask;
- pval[2] = (*--src32 >> 8) & mask;
- pval[3] = (*--src32 >> 8) & mask;
- }
-
- for (j = w; j > 0; j--) {
- v = *--src32;
- v1 = v & mask;
- *--dst32 = pval[0] | (v1 << 8);
- pval[0] = (v ^ v1) >> 8;
- v = *--src32;
- v1 = v & mask;
- *--dst32 = pval[1] | (v1 << 8);
- pval[1] = (v ^ v1) >> 8;
- v = *--src32;
- v1 = v & mask;
- *--dst32 = pval[2] | (v1 << 8);
- pval[2] = (v ^ v1) >> 8;
- v = *--src32;
- v1 = v & mask;
- *--dst32 = pval[3] | (v1 << 8);
- pval[3] = (v ^ v1) >> 8;
- }
-
- if (!(f & 2)) {
- dst32[-1] = (dst32[-1] & mask) | pval[0];
- dst32[-2] = (dst32[-2] & mask) | pval[1];
- dst32[-3] = (dst32[-3] & mask) | pval[2];
- dst32[-4] = (dst32[-4] & mask) | pval[3];
- }
-
- src -= next_line;
- dst -= next_line;
- }
- }
- }
-}
-
-void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
- int sy, int sx, int height, int width)
-{
- u32 *dest;
- int rows, i;
- u32 cval[4];
-
- dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
- if (sx & 15) {
- u8 *dest8 = (u8 *)dest + 1;
-
- expand8_col2mask(color, cval);
-
- for (i = height; i; i--) {
- fill8_col(dest8, cval);
- dest8 += next_line;
- }
- dest += BPL / 2;
- width -= 8;
- }
-
- expand16_col2mask(color, cval);
- rows = width >> 4;
- if (rows) {
- u32 *d = dest;
- u32 off = next_line - rows * BPL * 2;
- for (i = height; i; i--) {
- d = fill16_col(d, rows, cval);
- d = (u32 *)((long)d + off);
- }
- dest += rows * BPL / 2;
- width &= 15;
- }
-
- if (width) {
- u8 *dest8 = (u8 *)dest;
-
- expand8_col2mask(color, cval);
-
- for (i = height; i; i--) {
- fill8_col(dest8, cval);
- dest8 += next_line;
- }
- }
-}
-
-void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
- int dy, int dx, u32 width,
- const u8 *data, u32 bgcolor, u32 fgcolor)
-{
- u32 *dest;
- const u16 *data16;
- int rows;
- u32 fgm[4], bgm[4], m;
-
- dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
- if (dx & 15) {
- fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
- dest += BPL / 2;
- width -= 8;
- }
-
- if (width >= 16) {
- data16 = (const u16 *)data;
- expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
-
- for (rows = width / 16; rows; rows--) {
- u16 d = *data16++;
- m = d | ((u32)d << 16);
- *dest++ = (m & fgm[0]) ^ bgm[0];
- *dest++ = (m & fgm[1]) ^ bgm[1];
- *dest++ = (m & fgm[2]) ^ bgm[2];
- *dest++ = (m & fgm[3]) ^ bgm[3];
- }
-
- data = (const u8 *)data16;
- width &= 15;
- }
-
- if (width)
- fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
-}
diff --git a/drivers/video/fbdev/atafb_mfb.c b/drivers/video/fbdev/atafb_mfb.c
deleted file mode 100644
index 384fd3e4d..000000000
--- a/drivers/video/fbdev/atafb_mfb.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * linux/drivers/video/mfb.c -- Low level frame buffer operations for
- * monochrome
- *
- * Created 5 Apr 1997 by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- */
-
-#include <linux/string.h>
-#include <linux/fb.h>
-
-#include "atafb.h"
-#include "atafb_utils.h"
-
-
- /*
- * Monochrome
- */
-
-void atafb_mfb_copyarea(struct fb_info *info, u_long next_line,
- int sy, int sx, int dy, int dx,
- int height, int width)
-{
- u8 *src, *dest;
- u_int rows;
-
- if (sx == 0 && dx == 0 && width == next_line) {
- src = (u8 *)info->screen_base + sy * (width >> 3);
- dest = (u8 *)info->screen_base + dy * (width >> 3);
- fb_memmove(dest, src, height * (width >> 3));
- } else if (dy <= sy) {
- src = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
- dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
- for (rows = height; rows--;) {
- fb_memmove(dest, src, width >> 3);
- src += next_line;
- dest += next_line;
- }
- } else {
- src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3);
- dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3);
- for (rows = height; rows--;) {
- fb_memmove(dest, src, width >> 3);
- src -= next_line;
- dest -= next_line;
- }
- }
-}
-
-void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
- int sy, int sx, int height, int width)
-{
- u8 *dest;
- u_int rows;
-
- dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
-
- if (sx == 0 && width == next_line) {
- if (color)
- fb_memset255(dest, height * (width >> 3));
- else
- fb_memclear(dest, height * (width >> 3));
- } else {
- for (rows = height; rows--; dest += next_line) {
- if (color)
- fb_memset255(dest, width >> 3);
- else
- fb_memclear_small(dest, width >> 3);
- }
- }
-}
-
-void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
- int dy, int dx, u32 width,
- const u8 *data, u32 bgcolor, u32 fgcolor)
-{
- u8 *dest;
- u_int rows;
-
- dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
-
- for (rows = width / 8; rows--; /* check margins */ ) {
- // use fast_memmove or fb_memmove
- *dest++ = *data++;
- }
-}
diff --git a/drivers/video/fbdev/atafb_utils.h b/drivers/video/fbdev/atafb_utils.h
deleted file mode 100644
index 8f3396ea8..000000000
--- a/drivers/video/fbdev/atafb_utils.h
+++ /dev/null
@@ -1,401 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _VIDEO_ATAFB_UTILS_H
-#define _VIDEO_ATAFB_UTILS_H
-
-/* ================================================================= */
-/* Utility Assembler Functions */
-/* ================================================================= */
-
-/* ====================================================================== */
-
-/* Those of a delicate disposition might like to skip the next couple of
- * pages.
- *
- * These functions are drop in replacements for memmove and
- * memset(_, 0, _). However their five instances add at least a kilobyte
- * to the object file. You have been warned.
- *
- * Not a great fan of assembler for the sake of it, but I think
- * that these routines are at least 10 times faster than their C
- * equivalents for large blits, and that's important to the lowest level of
- * a graphics driver. Question is whether some scheme with the blitter
- * would be faster. I suspect not for simple text system - not much
- * asynchrony.
- *
- * Code is very simple, just gruesome expansion. Basic strategy is to
- * increase data moved/cleared at each step to 16 bytes to reduce
- * instruction per data move overhead. movem might be faster still
- * For more than 15 bytes, we try to align the write direction on a
- * longword boundary to get maximum speed. This is even more gruesome.
- * Unaligned read/write used requires 68020+ - think this is a problem?
- *
- * Sorry!
- */
-
-
-/* ++roman: I've optimized Robert's original versions in some minor
- * aspects, e.g. moveq instead of movel, let gcc choose the registers,
- * use movem in some places...
- * For other modes than 1 plane, lots of more such assembler functions
- * were needed (e.g. the ones using movep or expanding color values).
- */
-
-/* ++andreas: more optimizations:
- subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
- addal is faster than addaw
- movep is rather expensive compared to ordinary move's
- some functions rewritten in C for clarity, no speed loss */
-
-static inline void *fb_memclear_small(void *s, size_t count)
-{
- if (!count)
- return 0;
-
- asm volatile ("\n"
- " lsr.l #1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
- "1: lsr.l #1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
- "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
- "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
- "1:"
- : "=a" (s), "=d" (count)
- : "d" (0), "0" ((char *)s + count), "1" (count));
- asm volatile ("\n"
- " subq.l #1,%1\n"
- " jcs 3f\n"
- " move.l %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
- "2: movem.l %2/%%d4/%%d5/%%d6,-(%0)\n"
- " dbra %1,2b\n"
- "3:"
- : "=a" (s), "=d" (count)
- : "d" (0), "0" (s), "1" (count)
- : "d4", "d5", "d6"
- );
-
- return 0;
-}
-
-
-static inline void *fb_memclear(void *s, size_t count)
-{
- if (!count)
- return 0;
-
- if (count < 16) {
- asm volatile ("\n"
- " lsr.l #1,%1 ; jcc 1f ; clr.b (%0)+\n"
- "1: lsr.l #1,%1 ; jcc 1f ; clr.w (%0)+\n"
- "1: lsr.l #1,%1 ; jcc 1f ; clr.l (%0)+\n"
- "1: lsr.l #1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n"
- "1:"
- : "=a" (s), "=d" (count)
- : "0" (s), "1" (count));
- } else {
- long tmp;
- asm volatile ("\n"
- " move.l %1,%2\n"
- " lsr.l #1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n"
- " lsr.l #1,%2 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/
- " clr.w (%0)+ ; subq.w #2,%1 ; jra 2f\n"
- "1: lsr.l #1,%2 ; jcc 2f\n"
- " clr.w (%0)+ ; subq.w #2,%1\n"
- "2: move.w %1,%2; lsr.l #2,%1 ; jeq 6f\n"
- " lsr.l #1,%1 ; jcc 3f ; clr.l (%0)+\n"
- "3: lsr.l #1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n"
- "4: subq.l #1,%1 ; jcs 6f\n"
- "5: clr.l (%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n"
- " dbra %1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n"
- "6: move.w %2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n"
- "7: btst #0,%1 ; jeq 8f ; clr.b (%0)+\n"
- "8:"
- : "=a" (s), "=d" (count), "=d" (tmp)
- : "0" (s), "1" (count));
- }
-
- return 0;
-}
-
-
-static inline void *fb_memset255(void *s, size_t count)
-{
- if (!count)
- return 0;
-
- asm volatile ("\n"
- " lsr.l #1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
- "1: lsr.l #1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
- "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
- "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
- "1:"
- : "=a" (s), "=d" (count)
- : "d" (-1), "0" ((char *)s+count), "1" (count));
- asm volatile ("\n"
- " subq.l #1,%1 ; jcs 3f\n"
- " move.l %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
- "2: movem.l %2/%%d4/%%d5/%%d6,-(%0)\n"
- " dbra %1,2b\n"
- "3:"
- : "=a" (s), "=d" (count)
- : "d" (-1), "0" (s), "1" (count)
- : "d4", "d5", "d6");
-
- return 0;
-}
-
-
-static inline void *fb_memmove(void *d, const void *s, size_t count)
-{
- if (d < s) {
- if (count < 16) {
- asm volatile ("\n"
- " lsr.l #1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n"
- "1: lsr.l #1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n"
- "1: lsr.l #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n"
- "1: lsr.l #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
- "1:"
- : "=a" (d), "=a" (s), "=d" (count)
- : "0" (d), "1" (s), "2" (count));
- } else {
- long tmp;
- asm volatile ("\n"
- " move.l %0,%3\n"
- " lsr.l #1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n"
- " lsr.l #1,%3 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/
- " move.w (%1)+,(%0)+ ; subqw #2,%2 ; jra 2f\n"
- "1: lsr.l #1,%3 ; jcc 2f\n"
- " move.w (%1)+,(%0)+ ; subqw #2,%2\n"
- "2: move.w %2,%-; lsr.l #2,%2 ; jeq 6f\n"
- " lsr.l #1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n"
- "3: lsr.l #1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
- "4: subq.l #1,%2 ; jcs 6f\n"
- "5: move.l (%1)+,(%0)+; move.l (%1)+,(%0)+\n"
- " move.l (%1)+,(%0)+; move.l (%1)+,(%0)+\n"
- " dbra %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
- "6: move.w %+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n"
- "7: btst #0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n"
- "8:"
- : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
- : "0" (d), "1" (s), "2" (count));
- }
- } else {
- if (count < 16) {
- asm volatile ("\n"
- " lsr.l #1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n"
- "1: lsr.l #1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n"
- "1: lsr.l #1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n"
- "1: lsr.l #1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
- "1:"
- : "=a" (d), "=a" (s), "=d" (count)
- : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
- } else {
- long tmp;
-
- asm volatile ("\n"
- " move.l %0,%3\n"
- " lsr.l #1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n"
- " lsr.l #1,%3 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/
- " move.w -(%1),-(%0) ; subqw #2,%2 ; jra 2f\n"
- "1: lsr.l #1,%3 ; jcc 2f\n"
- " move.w -(%1),-(%0) ; subqw #2,%2\n"
- "2: move.w %2,%-; lsr.l #2,%2 ; jeq 6f\n"
- " lsr.l #1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n"
- "3: lsr.l #1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
- "4: subq.l #1,%2 ; jcs 6f\n"
- "5: move.l -(%1),-(%0); move.l -(%1),-(%0)\n"
- " move.l -(%1),-(%0); move.l -(%1),-(%0)\n"
- " dbra %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
- "6: move.w %+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n"
- "7: btst #0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n"
- "8:"
- : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
- : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
- }
- }
-
- return 0;
-}
-
-
-/* ++andreas: Simple and fast version of memmove, assumes size is
- divisible by 16, suitable for moving the whole screen bitplane */
-static inline void fast_memmove(char *dst, const char *src, size_t size)
-{
- if (!size)
- return;
- if (dst < src)
- asm volatile ("\n"
- "1: movem.l (%0)+,%%d0/%%d1/%%a0/%%a1\n"
- " movem.l %%d0/%%d1/%%a0/%%a1,%1@\n"
- " addq.l #8,%1; addq.l #8,%1\n"
- " dbra %2,1b\n"
- " clr.w %2; subq.l #1,%2\n"
- " jcc 1b"
- : "=a" (src), "=a" (dst), "=d" (size)
- : "0" (src), "1" (dst), "2" (size / 16 - 1)
- : "d0", "d1", "a0", "a1", "memory");
- else
- asm volatile ("\n"
- "1: subq.l #8,%0; subq.l #8,%0\n"
- " movem.l %0@,%%d0/%%d1/%%a0/%%a1\n"
- " movem.l %%d0/%%d1/%%a0/%%a1,-(%1)\n"
- " dbra %2,1b\n"
- " clr.w %2; subq.l #1,%2\n"
- " jcc 1b"
- : "=a" (src), "=a" (dst), "=d" (size)
- : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
- : "d0", "d1", "a0", "a1", "memory");
-}
-
-#ifdef BPL
-
-/*
- * This expands a up to 8 bit color into two longs
- * for movel operations.
- */
-static const u32 four2long[] = {
- 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
- 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
- 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
- 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff,
-};
-
-static inline void expand8_col2mask(u8 c, u32 m[])
-{
- m[0] = four2long[c & 15];
-#if BPL > 4
- m[1] = four2long[c >> 4];
-#endif
-}
-
-static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
-{
- fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]);
-#if BPL > 4
- fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]);
-#endif
-}
-
-/*
- * set an 8bit value to a color
- */
-static inline void fill8_col(u8 *dst, u32 m[])
-{
- u32 tmp = m[0];
- dst[0] = tmp;
- dst[2] = (tmp >>= 8);
-#if BPL > 2
- dst[4] = (tmp >>= 8);
- dst[6] = tmp >> 8;
-#endif
-#if BPL > 4
- tmp = m[1];
- dst[8] = tmp;
- dst[10] = (tmp >>= 8);
- dst[12] = (tmp >>= 8);
- dst[14] = tmp >> 8;
-#endif
-}
-
-/*
- * set an 8bit value according to foreground/background color
- */
-static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask)
-{
- u32 fgm[2], bgm[2], tmp;
-
- expand8_2col2mask(fg, bg, fgm, bgm);
-
- mask |= mask << 8;
-#if BPL > 2
- mask |= mask << 16;
-#endif
- tmp = (mask & fgm[0]) ^ bgm[0];
- dst[0] = tmp;
- dst[2] = (tmp >>= 8);
-#if BPL > 2
- dst[4] = (tmp >>= 8);
- dst[6] = tmp >> 8;
-#endif
-#if BPL > 4
- tmp = (mask & fgm[1]) ^ bgm[1];
- dst[8] = tmp;
- dst[10] = (tmp >>= 8);
- dst[12] = (tmp >>= 8);
- dst[14] = tmp >> 8;
-#endif
-}
-
-static const u32 two2word[] = {
- 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
-};
-
-static inline void expand16_col2mask(u8 c, u32 m[])
-{
- m[0] = two2word[c & 3];
-#if BPL > 2
- m[1] = two2word[(c >> 2) & 3];
-#endif
-#if BPL > 4
- m[2] = two2word[(c >> 4) & 3];
- m[3] = two2word[c >> 6];
-#endif
-}
-
-static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
-{
- bgm[0] = two2word[bg & 3];
- fgm[0] = two2word[fg & 3] ^ bgm[0];
-#if BPL > 2
- bgm[1] = two2word[(bg >> 2) & 3];
- fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1];
-#endif
-#if BPL > 4
- bgm[2] = two2word[(bg >> 4) & 3];
- fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2];
- bgm[3] = two2word[bg >> 6];
- fgm[3] = two2word[fg >> 6] ^ bgm[3];
-#endif
-}
-
-static inline u32 *fill16_col(u32 *dst, int rows, u32 m[])
-{
- while (rows) {
- *dst++ = m[0];
-#if BPL > 2
- *dst++ = m[1];
-#endif
-#if BPL > 4
- *dst++ = m[2];
- *dst++ = m[3];
-#endif
- rows--;
- }
- return dst;
-}
-
-static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes)
-{
- u32 *s, *d, v;
-
- s = src;
- d = dst;
- do {
- v = (*s++ & mask) | (*d & ~mask);
- *d++ = v;
-#if BPL > 2
- v = (*s++ & mask) | (*d & ~mask);
- *d++ = v;
-#endif
-#if BPL > 4
- v = (*s++ & mask) | (*d & ~mask);
- *d++ = v;
- v = (*s++ & mask) | (*d & ~mask);
- *d++ = v;
-#endif
- d = (u32 *)((u8 *)d + bytes);
- s = (u32 *)((u8 *)s + bytes);
- } while (--h);
-}
-
-#endif
-
-#endif /* _VIDEO_ATAFB_UTILS_H */
diff --git a/drivers/video/fbdev/hgafb.c b/drivers/video/fbdev/hgafb.c
deleted file mode 100644
index d32fd1c52..000000000
--- a/drivers/video/fbdev/hgafb.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- * linux/drivers/video/hgafb.c -- Hercules graphics adaptor frame buffer device
- *
- * Created 25 Nov 1999 by Ferenc Bakonyi (fero@drama.obuda.kando.hu)
- * Based on skeletonfb.c by Geert Uytterhoeven and
- * mdacon.c by Andrew Apted
- *
- * History:
- *
- * - Revision 0.1.8 (23 Oct 2002): Ported to new framebuffer api.
- *
- * - Revision 0.1.7 (23 Jan 2001): fix crash resulting from MDA only cards
- * being detected as Hercules. (Paul G.)
- * - Revision 0.1.6 (17 Aug 2000): new style structs
- * documentation
- * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
- * minor fixes
- * - Revision 0.1.4 (24 Jan 2000): fixed a bug in hga_card_detect() for
- * HGA-only systems
- * - Revision 0.1.3 (22 Jan 2000): modified for the new fb_info structure
- * screen is cleared after rmmod
- * virtual resolutions
- * module parameter 'nologo={0|1}'
- * the most important: boot logo :)
- * - Revision 0.1.0 (6 Dec 1999): faster scrolling and minor fixes
- * - First release (25 Nov 1999)
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <asm/io.h>
-#include <asm/vga.h>
-
-#if 0
-#define DPRINTK(args...) printk(KERN_DEBUG __FILE__": " ##args)
-#else
-#define DPRINTK(args...)
-#endif
-
-#if 0
-#define CHKINFO(ret) if (info != &fb_info) { printk(KERN_DEBUG __FILE__": This should never happen, line:%d \n", __LINE__); return ret; }
-#else
-#define CHKINFO(ret)
-#endif
-
-/* Description of the hardware layout */
-
-static void __iomem *hga_vram; /* Base of video memory */
-static unsigned long hga_vram_len; /* Size of video memory */
-
-#define HGA_ROWADDR(row) ((row%4)*8192 + (row>>2)*90)
-#define HGA_TXT 0
-#define HGA_GFX 1
-
-static inline u8 __iomem * rowaddr(struct fb_info *info, u_int row)
-{
- return info->screen_base + HGA_ROWADDR(row);
-}
-
-static int hga_mode = -1; /* 0 = txt, 1 = gfx mode */
-
-static enum { TYPE_HERC, TYPE_HERCPLUS, TYPE_HERCCOLOR } hga_type;
-static char *hga_type_name;
-
-#define HGA_INDEX_PORT 0x3b4 /* Register select port */
-#define HGA_VALUE_PORT 0x3b5 /* Register value port */
-#define HGA_MODE_PORT 0x3b8 /* Mode control port */
-#define HGA_STATUS_PORT 0x3ba /* Status and Config port */
-#define HGA_GFX_PORT 0x3bf /* Graphics control port */
-
-/* HGA register values */
-
-#define HGA_CURSOR_BLINKING 0x00
-#define HGA_CURSOR_OFF 0x20
-#define HGA_CURSOR_SLOWBLINK 0x60
-
-#define HGA_MODE_GRAPHICS 0x02
-#define HGA_MODE_VIDEO_EN 0x08
-#define HGA_MODE_BLINK_EN 0x20
-#define HGA_MODE_GFX_PAGE1 0x80
-
-#define HGA_STATUS_HSYNC 0x01
-#define HGA_STATUS_VSYNC 0x80
-#define HGA_STATUS_VIDEO 0x08
-
-#define HGA_CONFIG_COL132 0x08
-#define HGA_GFX_MODE_EN 0x01
-#define HGA_GFX_PAGE_EN 0x02
-
-/* Global locks */
-
-static DEFINE_SPINLOCK(hga_reg_lock);
-
-/* Framebuffer driver structures */
-
-static const struct fb_var_screeninfo hga_default_var = {
- .xres = 720,
- .yres = 348,
- .xres_virtual = 720,
- .yres_virtual = 348,
- .bits_per_pixel = 1,
- .red = {0, 1, 0},
- .green = {0, 1, 0},
- .blue = {0, 1, 0},
- .transp = {0, 0, 0},
- .height = -1,
- .width = -1,
-};
-
-static struct fb_fix_screeninfo hga_fix = {
- .id = "HGA",
- .type = FB_TYPE_PACKED_PIXELS, /* (not sure) */
- .visual = FB_VISUAL_MONO10,
- .xpanstep = 8,
- .ypanstep = 8,
- .line_length = 90,
- .accel = FB_ACCEL_NONE
-};
-
-/* Don't assume that tty1 will be the initial current console. */
-static int release_io_port = 0;
-static int release_io_ports = 0;
-static bool nologo = 0;
-
-/* -------------------------------------------------------------------------
- *
- * Low level hardware functions
- *
- * ------------------------------------------------------------------------- */
-
-static void write_hga_b(unsigned int val, unsigned char reg)
-{
- outb_p(reg, HGA_INDEX_PORT);
- outb_p(val, HGA_VALUE_PORT);
-}
-
-static void write_hga_w(unsigned int val, unsigned char reg)
-{
- outb_p(reg, HGA_INDEX_PORT); outb_p(val >> 8, HGA_VALUE_PORT);
- outb_p(reg+1, HGA_INDEX_PORT); outb_p(val & 0xff, HGA_VALUE_PORT);
-}
-
-static int test_hga_b(unsigned char val, unsigned char reg)
-{
- outb_p(reg, HGA_INDEX_PORT);
- outb (val, HGA_VALUE_PORT);
- udelay(20); val = (inb_p(HGA_VALUE_PORT) == val);
- return val;
-}
-
-static void hga_clear_screen(void)
-{
- unsigned char fillchar = 0xbf; /* magic */
- unsigned long flags;
-
- spin_lock_irqsave(&hga_reg_lock, flags);
- if (hga_mode == HGA_TXT)
- fillchar = ' ';
- else if (hga_mode == HGA_GFX)
- fillchar = 0x00;
- spin_unlock_irqrestore(&hga_reg_lock, flags);
- if (fillchar != 0xbf)
- memset_io(hga_vram, fillchar, hga_vram_len);
-}
-
-static void hga_txt_mode(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hga_reg_lock, flags);
- outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_BLINK_EN, HGA_MODE_PORT);
- outb_p(0x00, HGA_GFX_PORT);
- outb_p(0x00, HGA_STATUS_PORT);
-
- write_hga_b(0x61, 0x00); /* horizontal total */
- write_hga_b(0x50, 0x01); /* horizontal displayed */
- write_hga_b(0x52, 0x02); /* horizontal sync pos */
- write_hga_b(0x0f, 0x03); /* horizontal sync width */
-
- write_hga_b(0x19, 0x04); /* vertical total */
- write_hga_b(0x06, 0x05); /* vertical total adjust */
- write_hga_b(0x19, 0x06); /* vertical displayed */
- write_hga_b(0x19, 0x07); /* vertical sync pos */
-
- write_hga_b(0x02, 0x08); /* interlace mode */
- write_hga_b(0x0d, 0x09); /* maximum scanline */
- write_hga_b(0x0c, 0x0a); /* cursor start */
- write_hga_b(0x0d, 0x0b); /* cursor end */
-
- write_hga_w(0x0000, 0x0c); /* start address */
- write_hga_w(0x0000, 0x0e); /* cursor location */
-
- hga_mode = HGA_TXT;
- spin_unlock_irqrestore(&hga_reg_lock, flags);
-}
-
-static void hga_gfx_mode(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hga_reg_lock, flags);
- outb_p(0x00, HGA_STATUS_PORT);
- outb_p(HGA_GFX_MODE_EN, HGA_GFX_PORT);
- outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
-
- write_hga_b(0x35, 0x00); /* horizontal total */
- write_hga_b(0x2d, 0x01); /* horizontal displayed */
- write_hga_b(0x2e, 0x02); /* horizontal sync pos */
- write_hga_b(0x07, 0x03); /* horizontal sync width */
-
- write_hga_b(0x5b, 0x04); /* vertical total */
- write_hga_b(0x02, 0x05); /* vertical total adjust */
- write_hga_b(0x57, 0x06); /* vertical displayed */
- write_hga_b(0x57, 0x07); /* vertical sync pos */
-
- write_hga_b(0x02, 0x08); /* interlace mode */
- write_hga_b(0x03, 0x09); /* maximum scanline */
- write_hga_b(0x00, 0x0a); /* cursor start */
- write_hga_b(0x00, 0x0b); /* cursor end */
-
- write_hga_w(0x0000, 0x0c); /* start address */
- write_hga_w(0x0000, 0x0e); /* cursor location */
-
- hga_mode = HGA_GFX;
- spin_unlock_irqrestore(&hga_reg_lock, flags);
-}
-
-static void hga_show_logo(struct fb_info *info)
-{
-/*
- void __iomem *dest = hga_vram;
- char *logo = linux_logo_bw;
- int x, y;
-
- for (y = 134; y < 134 + 80 ; y++) * this needs some cleanup *
- for (x = 0; x < 10 ; x++)
- writeb(~*(logo++),(dest + HGA_ROWADDR(y) + x + 40));
-*/
-}
-
-static void hga_pan(unsigned int xoffset, unsigned int yoffset)
-{
- unsigned int base;
- unsigned long flags;
-
- base = (yoffset / 8) * 90 + xoffset;
- spin_lock_irqsave(&hga_reg_lock, flags);
- write_hga_w(base, 0x0c); /* start address */
- spin_unlock_irqrestore(&hga_reg_lock, flags);
- DPRINTK("hga_pan: base:%d\n", base);
-}
-
-static void hga_blank(int blank_mode)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hga_reg_lock, flags);
- if (blank_mode) {
- outb_p(0x00, HGA_MODE_PORT); /* disable video */
- } else {
- outb_p(HGA_MODE_VIDEO_EN | HGA_MODE_GRAPHICS, HGA_MODE_PORT);
- }
- spin_unlock_irqrestore(&hga_reg_lock, flags);
-}
-
-static int hga_card_detect(struct platform_device *pdev)
-{
- int count = 0;
- void __iomem *p, *q;
- unsigned short p_save, q_save;
-
- hga_vram_len = 0x08000;
-
- if (!devm_request_mem_region(&pdev->dev, 0xb0000, hga_vram_len, "hgafb")) {
- dev_err(&pdev->dev, "cannot reserve video memory at 0xb0000\n");
- return -EBUSY;
- }
-
- hga_vram = ioremap(0xb0000, hga_vram_len);
- if (!hga_vram)
- return -ENOMEM;
-
- if (request_region(0x3b0, 12, "hgafb"))
- release_io_ports = 1;
- if (request_region(0x3bf, 1, "hgafb"))
- release_io_port = 1;
-
- /* do a memory check */
-
- p = hga_vram;
- q = hga_vram + 0x01000;
-
- p_save = readw(p); q_save = readw(q);
-
- writew(0xaa55, p); if (readw(p) == 0xaa55) count++;
- writew(0x55aa, p); if (readw(p) == 0x55aa) count++;
- writew(p_save, p);
-
- if (count != 2)
- goto error;
-
- /* Ok, there is definitely a card registering at the correct
- * memory location, so now we do an I/O port test.
- */
-
- if (!test_hga_b(0x66, 0x0f)) /* cursor low register */
- goto error;
-
- if (!test_hga_b(0x99, 0x0f)) /* cursor low register */
- goto error;
-
- /* See if the card is a Hercules, by checking whether the vsync
- * bit of the status register is changing. This test lasts for
- * approximately 1/10th of a second.
- */
-
- p_save = q_save = inb_p(HGA_STATUS_PORT) & HGA_STATUS_VSYNC;
-
- for (count=0; count < 50000 && p_save == q_save; count++) {
- q_save = inb(HGA_STATUS_PORT) & HGA_STATUS_VSYNC;
- udelay(2);
- }
-
- if (p_save == q_save)
- goto error;
-
- switch (inb_p(HGA_STATUS_PORT) & 0x70) {
- case 0x10:
- hga_type = TYPE_HERCPLUS;
- hga_type_name = "HerculesPlus";
- break;
- case 0x50:
- hga_type = TYPE_HERCCOLOR;
- hga_type_name = "HerculesColor";
- break;
- default:
- hga_type = TYPE_HERC;
- hga_type_name = "Hercules";
- break;
- }
- return 0;
-error:
- if (release_io_ports)
- release_region(0x3b0, 12);
- if (release_io_port)
- release_region(0x3bf, 1);
-
- iounmap(hga_vram);
-
- pr_err("hgafb: HGA card not detected.\n");
-
- return -EINVAL;
-}
-
-/**
- * hgafb_open - open the framebuffer device
- * @info: pointer to fb_info object containing info for current hga board
- * @init: open by console system or userland.
- *
- * Returns: %0
- */
-
-static int hgafb_open(struct fb_info *info, int init)
-{
- hga_gfx_mode();
- hga_clear_screen();
- if (!nologo) hga_show_logo(info);
- return 0;
-}
-
-/**
- * hgafb_release - open the framebuffer device
- * @info: pointer to fb_info object containing info for current hga board
- * @init: open by console system or userland.
- *
- * Returns: %0
- */
-
-static int hgafb_release(struct fb_info *info, int init)
-{
- hga_txt_mode();
- hga_clear_screen();
- return 0;
-}
-
-/**
- * hgafb_setcolreg - set color registers
- * @regno:register index to set
- * @red:red value, unused
- * @green:green value, unused
- * @blue:blue value, unused
- * @transp:transparency value, unused
- * @info:unused
- *
- * This callback function is used to set the color registers of a HGA
- * board. Since we have only two fixed colors only @regno is checked.
- * A zero is returned on success and 1 for failure.
- *
- * Returns: %0
- */
-
-static int hgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
-{
- if (regno > 1)
- return 1;
- return 0;
-}
-
-/**
- * hgafb_pan_display - pan or wrap the display
- * @var:contains new xoffset, yoffset and vmode values
- * @info:pointer to fb_info object containing info for current hga board
- *
- * This function looks only at xoffset, yoffset and the %FB_VMODE_YWRAP
- * flag in @var. If input parameters are correct it calls hga_pan() to
- * program the hardware. @info->var is updated to the new values.
- *
- * Returns: %0 on success or %-EINVAL for failure.
- */
-
-static int hgafb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- if (var->vmode & FB_VMODE_YWRAP) {
- if (var->yoffset >= info->var.yres_virtual ||
- var->xoffset)
- return -EINVAL;
- } else {
- if (var->xoffset + info->var.xres > info->var.xres_virtual
- || var->yoffset + info->var.yres > info->var.yres_virtual
- || var->yoffset % 8)
- return -EINVAL;
- }
-
- hga_pan(var->xoffset, var->yoffset);
- return 0;
-}
-
-/**
- * hgafb_blank - (un)blank the screen
- * @blank_mode:blanking method to use
- * @info:unused
- *
- * Blank the screen if blank_mode != 0, else unblank.
- * Implements VESA suspend and powerdown modes on hardware that supports
- * disabling hsync/vsync:
- * @blank_mode == 2 means suspend vsync,
- * @blank_mode == 3 means suspend hsync,
- * @blank_mode == 4 means powerdown.
- *
- * Returns: %0
- */
-
-static int hgafb_blank(int blank_mode, struct fb_info *info)
-{
- hga_blank(blank_mode);
- return 0;
-}
-
-/*
- * Accel functions
- */
-static void hgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- u_int rows, y;
- u8 __iomem *dest;
-
- y = rect->dy;
-
- for (rows = rect->height; rows--; y++) {
- dest = rowaddr(info, y) + (rect->dx >> 3);
- switch (rect->rop) {
- case ROP_COPY:
- memset_io(dest, rect->color, (rect->width >> 3));
- break;
- case ROP_XOR:
- fb_writeb(~(fb_readb(dest)), dest);
- break;
- }
- }
-}
-
-static void hgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
- u_int rows, y1, y2;
- u8 __iomem *src;
- u8 __iomem *dest;
-
- if (area->dy <= area->sy) {
- y1 = area->sy;
- y2 = area->dy;
-
- for (rows = area->height; rows--; ) {
- src = rowaddr(info, y1) + (area->sx >> 3);
- dest = rowaddr(info, y2) + (area->dx >> 3);
- memmove(dest, src, (area->width >> 3));
- y1++;
- y2++;
- }
- } else {
- y1 = area->sy + area->height - 1;
- y2 = area->dy + area->height - 1;
-
- for (rows = area->height; rows--;) {
- src = rowaddr(info, y1) + (area->sx >> 3);
- dest = rowaddr(info, y2) + (area->dx >> 3);
- memmove(dest, src, (area->width >> 3));
- y1--;
- y2--;
- }
- }
-}
-
-static void hgafb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- u8 __iomem *dest;
- u8 *cdat = (u8 *) image->data;
- u_int rows, y = image->dy;
- u_int x;
- u8 d;
-
- for (rows = image->height; rows--; y++) {
- for (x = 0; x < image->width; x+= 8) {
- d = *cdat++;
- dest = rowaddr(info, y) + ((image->dx + x)>> 3);
- fb_writeb(d, dest);
- }
- }
-}
-
-static const struct fb_ops hgafb_ops = {
- .owner = THIS_MODULE,
- .fb_open = hgafb_open,
- .fb_release = hgafb_release,
- __FB_DEFAULT_IOMEM_OPS_RDWR,
- .fb_setcolreg = hgafb_setcolreg,
- .fb_pan_display = hgafb_pan_display,
- .fb_blank = hgafb_blank,
- .fb_fillrect = hgafb_fillrect,
- .fb_copyarea = hgafb_copyarea,
- .fb_imageblit = hgafb_imageblit,
- __FB_DEFAULT_IOMEM_OPS_MMAP,
-};
-
-/* ------------------------------------------------------------------------- *
- *
- * Functions in fb_info
- *
- * ------------------------------------------------------------------------- */
-
-/* ------------------------------------------------------------------------- */
-
- /*
- * Initialization
- */
-
-static int hgafb_probe(struct platform_device *pdev)
-{
- struct fb_info *info;
- int ret;
-
- ret = hga_card_detect(pdev);
- if (ret)
- return ret;
-
- printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
- hga_type_name, hga_vram_len/1024);
-
- info = framebuffer_alloc(0, &pdev->dev);
- if (!info) {
- iounmap(hga_vram);
- return -ENOMEM;
- }
-
- hga_fix.smem_start = (unsigned long)hga_vram;
- hga_fix.smem_len = hga_vram_len;
-
- info->flags = FBINFO_HWACCEL_YPAN;
- info->var = hga_default_var;
- info->fix = hga_fix;
- info->monspecs.hfmin = 0;
- info->monspecs.hfmax = 0;
- info->monspecs.vfmin = 10000;
- info->monspecs.vfmax = 10000;
- info->monspecs.dpms = 0;
- info->fbops = &hgafb_ops;
- info->screen_base = hga_vram;
-
- if (register_framebuffer(info) < 0) {
- framebuffer_release(info);
- iounmap(hga_vram);
- return -EINVAL;
- }
-
- fb_info(info, "%s frame buffer device\n", info->fix.id);
- platform_set_drvdata(pdev, info);
- return 0;
-}
-
-static void hgafb_remove(struct platform_device *pdev)
-{
- struct fb_info *info = platform_get_drvdata(pdev);
-
- hga_txt_mode();
- hga_clear_screen();
-
- if (info) {
- unregister_framebuffer(info);
- framebuffer_release(info);
- }
-
- iounmap(hga_vram);
-
- if (release_io_ports)
- release_region(0x3b0, 12);
-
- if (release_io_port)
- release_region(0x3bf, 1);
-}
-
-static struct platform_driver hgafb_driver = {
- .probe = hgafb_probe,
- .remove = hgafb_remove,
- .driver = {
- .name = "hgafb",
- },
-};
-
-static struct platform_device *hgafb_device;
-
-static int __init hgafb_init(void)
-{
- int ret;
-
- if (fb_get_options("hgafb", NULL))
- return -ENODEV;
-
- ret = platform_driver_register(&hgafb_driver);
-
- if (!ret) {
- hgafb_device = platform_device_register_simple("hgafb", 0, NULL, 0);
-
- if (IS_ERR(hgafb_device)) {
- platform_driver_unregister(&hgafb_driver);
- ret = PTR_ERR(hgafb_device);
- }
- }
-
- return ret;
-}
-
-static void __exit hgafb_exit(void)
-{
- platform_device_unregister(hgafb_device);
- platform_driver_unregister(&hgafb_driver);
-}
-
-/* -------------------------------------------------------------------------
- *
- * Modularization
- *
- * ------------------------------------------------------------------------- */
-
-MODULE_AUTHOR("Ferenc Bakonyi <fero@drama.obuda.kando.hu>");
-MODULE_DESCRIPTION("FBDev driver for Hercules Graphics Adaptor");
-MODULE_LICENSE("GPL");
-
-module_param(nologo, bool, 0);
-MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)");
-module_init(hgafb_init);
-module_exit(hgafb_exit);
diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c
deleted file mode 100644
index 22085d366..000000000
--- a/drivers/video/fbdev/vga16fb.c
+++ /dev/null
@@ -1,1442 +0,0 @@
-/*
- * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver
- *
- * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
- * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
- * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
- */
-
-#include <linux/aperture.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/sysfb.h>
-
-#include <asm/io.h>
-#include <video/vga.h>
-
-#define MODE_SKIP4 1
-#define MODE_8BPP 2
-#define MODE_CFB 4
-#define MODE_TEXT 8
-
-/* --------------------------------------------------------------------- */
-
-/*
- * card parameters
- */
-
-struct vga16fb_par {
- /* structure holding original VGA register settings when the
- screen is blanked */
- struct {
- unsigned char SeqCtrlIndex; /* Sequencer Index reg. */
- unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */
- unsigned char CrtMiscIO; /* Miscellaneous register */
- unsigned char HorizontalTotal; /* CRT-Controller:00h */
- unsigned char HorizDisplayEnd; /* CRT-Controller:01h */
- unsigned char StartHorizRetrace;/* CRT-Controller:04h */
- unsigned char EndHorizRetrace; /* CRT-Controller:05h */
- unsigned char Overflow; /* CRT-Controller:07h */
- unsigned char StartVertRetrace; /* CRT-Controller:10h */
- unsigned char EndVertRetrace; /* CRT-Controller:11h */
- unsigned char ModeControl; /* CRT-Controller:17h */
- unsigned char ClockingMode; /* Seq-Controller:01h */
- } vga_state;
- struct vgastate state;
- unsigned int ref_count;
- int palette_blanked, vesa_blanked, mode, isVGA;
- u8 misc, pel_msk, vss, clkdiv;
- u8 crtc[VGA_CRT_C];
-};
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo vga16fb_defined = {
- .xres = 640,
- .yres = 480,
- .xres_virtual = 640,
- .yres_virtual = 480,
- .bits_per_pixel = 4,
- .activate = FB_ACTIVATE_TEST,
- .height = -1,
- .width = -1,
- .pixclock = 39721,
- .left_margin = 48,
- .right_margin = 16,
- .upper_margin = 33,
- .lower_margin = 10,
- .hsync_len = 96,
- .vsync_len = 2,
- .vmode = FB_VMODE_NONINTERLACED,
-};
-
-/* name should not depend on EGA/VGA */
-static const struct fb_fix_screeninfo vga16fb_fix = {
- .id = "VGA16 VGA",
- .smem_start = VGA_FB_PHYS_BASE,
- .smem_len = VGA_FB_PHYS_SIZE,
- .type = FB_TYPE_VGA_PLANES,
- .type_aux = FB_AUX_VGA_PLANES_VGA4,
- .visual = FB_VISUAL_PSEUDOCOLOR,
- .xpanstep = 8,
- .ypanstep = 1,
- .line_length = 640 / 8,
- .accel = FB_ACCEL_NONE
-};
-
-/* The VGA's weird architecture often requires that we read a byte and
- write a byte to the same location. It doesn't matter *what* byte
- we write, however. This is because all the action goes on behind
- the scenes in the VGA's 32-bit latch register, and reading and writing
- video memory just invokes latch behavior.
-
- To avoid race conditions (is this necessary?), reading and writing
- the memory byte should be done with a single instruction. One
- suitable instruction is the x86 bitwise OR. The following
- read-modify-write routine should optimize to one such bitwise
- OR. */
-static inline void rmw(volatile char __iomem *p)
-{
- readb(p);
- writeb(1, p);
-}
-
-/* Set the Graphics Mode Register, and return its previous value.
- Bits 0-1 are write mode, bit 3 is read mode. */
-static inline int setmode(int mode)
-{
- int oldmode;
-
- oldmode = vga_io_rgfx(VGA_GFX_MODE);
- vga_io_w(VGA_GFX_D, mode);
- return oldmode;
-}
-
-/* Select the Bit Mask Register and return its value. */
-static inline int selectmask(void)
-{
- return vga_io_rgfx(VGA_GFX_BIT_MASK);
-}
-
-/* Set the value of the Bit Mask Register. It must already have been
- selected with selectmask(). */
-static inline void setmask(int mask)
-{
- vga_io_w(VGA_GFX_D, mask);
-}
-
-/* Set the Data Rotate Register and return its old value.
- Bits 0-2 are rotate count, bits 3-4 are logical operation
- (0=NOP, 1=AND, 2=OR, 3=XOR). */
-static inline int setop(int op)
-{
- int oldop;
-
- oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
- vga_io_w(VGA_GFX_D, op);
- return oldop;
-}
-
-/* Set the Enable Set/Reset Register and return its old value.
- The code here always uses value 0xf for this register. */
-static inline int setsr(int sr)
-{
- int oldsr;
-
- oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
- vga_io_w(VGA_GFX_D, sr);
- return oldsr;
-}
-
-/* Set the Set/Reset Register and return its old value. */
-static inline int setcolor(int color)
-{
- int oldcolor;
-
- oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
- vga_io_w(VGA_GFX_D, color);
- return oldcolor;
-}
-
-/* Return the value in the Graphics Address Register. */
-static inline int getindex(void)
-{
- return vga_io_r(VGA_GFX_I);
-}
-
-/* Set the value in the Graphics Address Register. */
-static inline void setindex(int index)
-{
- vga_io_w(VGA_GFX_I, index);
-}
-
-/* Check if the video mode is supported by the driver */
-static inline int check_mode_supported(const struct screen_info *si)
-{
- unsigned int type = screen_info_video_type(si);
-
- /* only EGA and VGA in 16 color graphic mode are supported */
- if (type != VIDEO_TYPE_EGAC && type != VIDEO_TYPE_VGAC)
- return -ENODEV;
-
- if (si->orig_video_mode != 0x0D && /* 320x200/4 (EGA) */
- si->orig_video_mode != 0x0E && /* 640x200/4 (EGA) */
- si->orig_video_mode != 0x10 && /* 640x350/4 (EGA) */
- si->orig_video_mode != 0x12) /* 640x480/4 (VGA) */
- return -ENODEV;
-
- return 0;
-}
-
-static void vga16fb_pan_var(struct fb_info *info,
- struct fb_var_screeninfo *var)
-{
- struct vga16fb_par *par = info->par;
- u32 xoffset, pos;
-
- xoffset = var->xoffset;
- if (info->var.bits_per_pixel == 8) {
- pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 2;
- } else if (par->mode & MODE_TEXT) {
- int fh = 16; // FIXME !!! font height. Fugde for now.
- pos = (info->var.xres_virtual * (var->yoffset / fh) + xoffset) >> 3;
- } else {
- if (info->var.nonstd)
- xoffset--;
- pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 3;
- }
- vga_io_wcrt(VGA_CRTC_START_HI, pos >> 8);
- vga_io_wcrt(VGA_CRTC_START_LO, pos & 0xFF);
- /* if we support CFB4, then we must! support xoffset with pixel
- * granularity if someone supports xoffset in bit resolution */
- vga_io_r(VGA_IS1_RC); /* reset flip-flop */
- vga_io_w(VGA_ATT_IW, VGA_ATC_PEL);
- if (info->var.bits_per_pixel == 8)
- vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1);
- else
- vga_io_w(VGA_ATT_IW, xoffset & 7);
- vga_io_r(VGA_IS1_RC);
- vga_io_w(VGA_ATT_IW, 0x20);
-}
-
-static void vga16fb_update_fix(struct fb_info *info)
-{
- if (info->var.bits_per_pixel == 4) {
- if (info->var.nonstd) {
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.line_length = info->var.xres_virtual / 2;
- } else {
- info->fix.type = FB_TYPE_VGA_PLANES;
- info->fix.type_aux = FB_AUX_VGA_PLANES_VGA4;
- info->fix.line_length = info->var.xres_virtual / 8;
- }
- } else if (info->var.bits_per_pixel == 0) {
- info->fix.type = FB_TYPE_TEXT;
- info->fix.type_aux = FB_AUX_TEXT_CGA;
- info->fix.line_length = info->var.xres_virtual / 4;
- } else { /* 8bpp */
- if (info->var.nonstd) {
- info->fix.type = FB_TYPE_VGA_PLANES;
- info->fix.type_aux = FB_AUX_VGA_PLANES_CFB8;
- info->fix.line_length = info->var.xres_virtual / 4;
- } else {
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.line_length = info->var.xres_virtual;
- }
- }
-}
-
-static void vga16fb_clock_chip(struct vga16fb_par *par,
- unsigned int *pixclock,
- const struct fb_info *info,
- int mul, int div)
-{
- static const struct {
- u32 pixclock;
- u8 misc;
- u8 seq_clock_mode;
- } *ptr, *best, vgaclocks[] = {
- { 79442 /* 12.587 */, 0x00, 0x08},
- { 70616 /* 14.161 */, 0x04, 0x08},
- { 39721 /* 25.175 */, 0x00, 0x00},
- { 35308 /* 28.322 */, 0x04, 0x00},
- { 0 /* bad */, 0x00, 0x00}};
- int err;
-
- *pixclock = (*pixclock * mul) / div;
- best = vgaclocks;
- err = *pixclock - best->pixclock;
- if (err < 0) err = -err;
- for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) {
- int tmp;
-
- tmp = *pixclock - ptr->pixclock;
- if (tmp < 0) tmp = -tmp;
- if (tmp < err) {
- err = tmp;
- best = ptr;
- }
- }
- par->misc |= best->misc;
- par->clkdiv = best->seq_clock_mode;
- *pixclock = (best->pixclock * div) / mul;
-}
-
-#define FAIL(X) return -EINVAL
-
-static int vga16fb_open(struct fb_info *info, int user)
-{
- struct vga16fb_par *par = info->par;
-
- if (!par->ref_count) {
- memset(&par->state, 0, sizeof(struct vgastate));
- par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
- VGA_SAVE_CMAP;
- save_vga(&par->state);
- }
- par->ref_count++;
-
- return 0;
-}
-
-static int vga16fb_release(struct fb_info *info, int user)
-{
- struct vga16fb_par *par = info->par;
-
- if (!par->ref_count)
- return -EINVAL;
-
- if (par->ref_count == 1)
- restore_vga(&par->state);
- par->ref_count--;
-
- return 0;
-}
-
-static int vga16fb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- struct vga16fb_par *par = info->par;
- u32 xres, right, hslen, left, xtotal;
- u32 yres, lower, vslen, upper, ytotal;
- u32 vxres, xoffset, vyres, yoffset;
- u32 pos;
- u8 r7, rMode;
- int shift;
- int mode;
- u32 maxmem;
-
- par->pel_msk = 0xFF;
-
- if (var->bits_per_pixel == 4) {
- if (var->nonstd) {
- if (!par->isVGA)
- return -EINVAL;
- shift = 3;
- mode = MODE_SKIP4 | MODE_CFB;
- maxmem = 16384;
- par->pel_msk = 0x0F;
- } else {
- shift = 3;
- mode = 0;
- maxmem = 65536;
- }
- } else if (var->bits_per_pixel == 8) {
- if (!par->isVGA)
- return -EINVAL; /* no support on EGA */
- shift = 2;
- if (var->nonstd) {
- mode = MODE_8BPP | MODE_CFB;
- maxmem = 65536;
- } else {
- mode = MODE_SKIP4 | MODE_8BPP | MODE_CFB;
- maxmem = 16384;
- }
- } else
- return -EINVAL;
-
- xres = (var->xres + 7) & ~7;
- vxres = (var->xres_virtual + 0xF) & ~0xF;
- xoffset = (var->xoffset + 7) & ~7;
- left = (var->left_margin + 7) & ~7;
- right = (var->right_margin + 7) & ~7;
- hslen = (var->hsync_len + 7) & ~7;
-
- if (vxres < xres)
- vxres = xres;
- if (xres + xoffset > vxres)
- xoffset = vxres - xres;
-
- var->xres = xres;
- var->right_margin = right;
- var->hsync_len = hslen;
- var->left_margin = left;
- var->xres_virtual = vxres;
- var->xoffset = xoffset;
-
- xres >>= shift;
- right >>= shift;
- hslen >>= shift;
- left >>= shift;
- vxres >>= shift;
- xtotal = xres + right + hslen + left;
- if (xtotal >= 256)
- FAIL("xtotal too big");
- if (hslen > 32)
- FAIL("hslen too big");
- if (right + hslen + left > 64)
- FAIL("hblank too big");
- par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5;
- par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1;
- par->crtc[VGA_CRTC_H_DISP] = xres - 1;
- pos = xres + right;
- par->crtc[VGA_CRTC_H_SYNC_START] = pos;
- pos += hslen;
- par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F;
- pos += left - 2; /* blank_end + 2 <= total + 5 */
- par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
- if (pos & 0x20)
- par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80;
-
- yres = var->yres;
- lower = var->lower_margin;
- vslen = var->vsync_len;
- upper = var->upper_margin;
- vyres = var->yres_virtual;
- yoffset = var->yoffset;
-
- if (yres > vyres)
- vyres = yres;
- if (vxres * vyres > maxmem) {
- vyres = maxmem / vxres;
- if (vyres < yres)
- return -ENOMEM;
- }
- if (yoffset + yres > vyres)
- yoffset = vyres - yres;
- var->yres = yres;
- var->lower_margin = lower;
- var->vsync_len = vslen;
- var->upper_margin = upper;
- var->yres_virtual = vyres;
- var->yoffset = yoffset;
-
- if (var->vmode & FB_VMODE_DOUBLE) {
- yres <<= 1;
- lower <<= 1;
- vslen <<= 1;
- upper <<= 1;
- }
- ytotal = yres + lower + vslen + upper;
- if (ytotal > 1024) {
- ytotal >>= 1;
- yres >>= 1;
- lower >>= 1;
- vslen >>= 1;
- upper >>= 1;
- rMode = 0x04;
- } else
- rMode = 0x00;
- if (ytotal > 1024)
- FAIL("ytotal too big");
- if (vslen > 16)
- FAIL("vslen too big");
- par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
- r7 = 0x10; /* disable linecompare */
- if (ytotal & 0x100) r7 |= 0x01;
- if (ytotal & 0x200) r7 |= 0x20;
- par->crtc[VGA_CRTC_PRESET_ROW] = 0;
- par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */
- if (var->vmode & FB_VMODE_DOUBLE)
- par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
- par->crtc[VGA_CRTC_CURSOR_START] = 0x20;
- par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
- if ((mode & (MODE_CFB | MODE_8BPP)) == MODE_CFB)
- xoffset--;
- pos = yoffset * vxres + (xoffset >> shift);
- par->crtc[VGA_CRTC_START_HI] = pos >> 8;
- par->crtc[VGA_CRTC_START_LO] = pos & 0xFF;
- par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
- par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
- pos = yres - 1;
- par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF;
- par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF;
- if (pos & 0x100)
- r7 |= 0x0A; /* 0x02 -> DISP_END, 0x08 -> BLANK_START */
- if (pos & 0x200) {
- r7 |= 0x40; /* 0x40 -> DISP_END */
- par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
- }
- pos += lower;
- par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF;
- if (pos & 0x100)
- r7 |= 0x04;
- if (pos & 0x200)
- r7 |= 0x80;
- pos += vslen;
- par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */
- pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
- par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
- but some SVGA chips requires all 8 bits to set */
- if (vxres >= 512)
- FAIL("vxres too long");
- par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
- if (mode & MODE_SKIP4)
- par->crtc[VGA_CRTC_UNDERLINE] = 0x5F; /* 256, cfb8 */
- else
- par->crtc[VGA_CRTC_UNDERLINE] = 0x1F; /* 16, vgap */
- par->crtc[VGA_CRTC_MODE] = rMode | ((mode & MODE_TEXT) ? 0xA3 : 0xE3);
- par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
- par->crtc[VGA_CRTC_OVERFLOW] = r7;
-
- par->vss = 0x00; /* 3DA */
-
- par->misc = 0xE3; /* enable CPU, ports 0x3Dx, positive sync */
- if (var->sync & FB_SYNC_HOR_HIGH_ACT)
- par->misc &= ~0x40;
- if (var->sync & FB_SYNC_VERT_HIGH_ACT)
- par->misc &= ~0x80;
-
- par->mode = mode;
-
- if (mode & MODE_8BPP)
- /* pixel clock == vga clock / 2 */
- vga16fb_clock_chip(par, &var->pixclock, info, 1, 2);
- else
- /* pixel clock == vga clock */
- vga16fb_clock_chip(par, &var->pixclock, info, 1, 1);
-
- var->red.offset = var->green.offset = var->blue.offset =
- var->transp.offset = 0;
- var->red.length = var->green.length = var->blue.length =
- (par->isVGA) ? 6 : 2;
- var->transp.length = 0;
- var->activate = FB_ACTIVATE_NOW;
- var->height = -1;
- var->width = -1;
- var->accel_flags = 0;
- return 0;
-}
-#undef FAIL
-
-static int vga16fb_set_par(struct fb_info *info)
-{
- struct vga16fb_par *par = info->par;
- u8 gdc[VGA_GFX_C];
- u8 seq[VGA_SEQ_C];
- u8 atc[VGA_ATT_C];
- int fh, i;
-
- seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv;
- if (par->mode & MODE_TEXT)
- seq[VGA_SEQ_PLANE_WRITE] = 0x03;
- else
- seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
- seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
- if (par->mode & MODE_TEXT)
- seq[VGA_SEQ_MEMORY_MODE] = 0x03;
- else if (par->mode & MODE_SKIP4)
- seq[VGA_SEQ_MEMORY_MODE] = 0x0E;
- else
- seq[VGA_SEQ_MEMORY_MODE] = 0x06;
-
- gdc[VGA_GFX_SR_VALUE] = 0x00;
- gdc[VGA_GFX_SR_ENABLE] = 0x00;
- gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
- gdc[VGA_GFX_DATA_ROTATE] = 0x00;
- gdc[VGA_GFX_PLANE_READ] = 0;
- if (par->mode & MODE_TEXT) {
- gdc[VGA_GFX_MODE] = 0x10;
- gdc[VGA_GFX_MISC] = 0x06;
- } else {
- if (par->mode & MODE_CFB)
- gdc[VGA_GFX_MODE] = 0x40;
- else
- gdc[VGA_GFX_MODE] = 0x00;
- gdc[VGA_GFX_MISC] = 0x05;
- }
- gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
- gdc[VGA_GFX_BIT_MASK] = 0xFF;
-
- for (i = 0x00; i < 0x10; i++)
- atc[i] = i;
- if (par->mode & MODE_TEXT)
- atc[VGA_ATC_MODE] = 0x04;
- else if (par->mode & MODE_8BPP)
- atc[VGA_ATC_MODE] = 0x41;
- else
- atc[VGA_ATC_MODE] = 0x81;
- atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */
- atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
- if (par->mode & MODE_8BPP)
- atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1;
- else
- atc[VGA_ATC_PEL] = info->var.xoffset & 7;
- atc[VGA_ATC_COLOR_PAGE] = 0x00;
-
- if (par->mode & MODE_TEXT) {
- fh = 16; // FIXME !!! Fudge font height.
- par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN]
- & ~0x1F) | (fh - 1);
- }
-
- vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01);
-
- /* Enable graphics register modification */
- if (!par->isVGA) {
- vga_io_w(EGA_GFX_E0, 0x00);
- vga_io_w(EGA_GFX_E1, 0x01);
- }
-
- /* update misc output register */
- vga_io_w(VGA_MIS_W, par->misc);
-
- /* synchronous reset on */
- vga_io_wseq(0x00, 0x01);
-
- if (par->isVGA)
- vga_io_w(VGA_PEL_MSK, par->pel_msk);
-
- /* write sequencer registers */
- vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20);
- for (i = 2; i < VGA_SEQ_C; i++) {
- vga_io_wseq(i, seq[i]);
- }
-
- /* synchronous reset off */
- vga_io_wseq(0x00, 0x03);
-
- /* deprotect CRT registers 0-7 */
- vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
-
- /* write CRT registers */
- for (i = 0; i < VGA_CRTC_REGS; i++) {
- vga_io_wcrt(i, par->crtc[i]);
- }
-
- /* write graphics controller registers */
- for (i = 0; i < VGA_GFX_C; i++) {
- vga_io_wgfx(i, gdc[i]);
- }
-
- /* write attribute controller registers */
- for (i = 0; i < VGA_ATT_C; i++) {
- vga_io_r(VGA_IS1_RC); /* reset flip-flop */
- vga_io_wattr(i, atc[i]);
- }
-
- /* Wait for screen to stabilize. */
- mdelay(50);
-
- vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]);
-
- vga_io_r(VGA_IS1_RC);
- vga_io_w(VGA_ATT_IW, 0x20);
-
- vga16fb_update_fix(info);
- return 0;
-}
-
-static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
-{
- static const unsigned char map[] = { 000, 001, 010, 011 };
- int val;
-
- if (regno >= 16)
- return;
- val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2);
- vga_io_r(VGA_IS1_RC); /* ! 0x3BA */
- vga_io_wattr(regno, val);
- vga_io_r(VGA_IS1_RC); /* some clones need it */
- vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */
-}
-
-static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
-{
- outb(regno, VGA_PEL_IW);
- outb(red >> 10, VGA_PEL_D);
- outb(green >> 10, VGA_PEL_D);
- outb(blue >> 10, VGA_PEL_D);
-}
-
-static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- struct vga16fb_par *par = info->par;
- int gray;
-
- /*
- * Set a single color register. The values supplied are
- * already rounded down to the hardware's capabilities
- * (according to the entries in the `var' structure). Return
- * != 0 for invalid regno.
- */
-
- if (regno >= 256)
- return 1;
-
- gray = info->var.grayscale;
-
- if (gray) {
- /* gray = 0.30*R + 0.59*G + 0.11*B */
- red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
- }
- if (par->isVGA)
- vga16_setpalette(regno,red,green,blue);
- else
- ega16_setpalette(regno,red,green,blue);
- return 0;
-}
-
-static int vga16fb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- vga16fb_pan_var(info, var);
- return 0;
-}
-
-/* The following VESA blanking code is taken from vgacon.c. The VGA
- blanking code was originally by Huang shi chao, and modified by
- Christoph Rimek (chrimek@toppoint.de) and todd j. derr
- (tjd@barefoot.org) for Linux. */
-
-static void vga_vesa_blank(struct vga16fb_par *par, int mode)
-{
- unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
- unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
-
- /* save original values of VGA controller registers */
- if(!par->vesa_blanked) {
- par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
- //sti();
-
- par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */
- par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01); /* HorizDisplayEnd */
- par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04); /* StartHorizRetrace */
- par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05); /* EndHorizRetrace */
- par->vga_state.Overflow = vga_io_rcrt(0x07); /* Overflow */
- par->vga_state.StartVertRetrace = vga_io_rcrt(0x10); /* StartVertRetrace */
- par->vga_state.EndVertRetrace = vga_io_rcrt(0x11); /* EndVertRetrace */
- par->vga_state.ModeControl = vga_io_rcrt(0x17); /* ModeControl */
- par->vga_state.ClockingMode = vga_io_rseq(0x01); /* ClockingMode */
- }
-
- /* assure that video is enabled */
- /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
- vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
-
- /* test for vertical retrace in process.... */
- if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
- vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
-
- /*
- * Set <End of vertical retrace> to minimum (0) and
- * <Start of vertical Retrace> to maximum (incl. overflow)
- * Result: turn off vertical sync (VSync) pulse.
- */
- if (mode & FB_BLANK_VSYNC_SUSPEND) {
- vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
- vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
- /* bits 9,10 of vert. retrace */
- vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
- }
-
- if (mode & FB_BLANK_HSYNC_SUSPEND) {
- /*
- * Set <End of horizontal retrace> to minimum (0) and
- * <Start of horizontal Retrace> to maximum
- * Result: turn off horizontal sync (HSync) pulse.
- */
- vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
- vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
- }
-
- /* restore both index registers */
- outb_p(SeqCtrlIndex, VGA_SEQ_I);
- outb_p(CrtCtrlIndex, VGA_CRT_IC);
-}
-
-static void vga_vesa_unblank(struct vga16fb_par *par)
-{
- unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
- unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
-
- /* restore original values of VGA controller registers */
- vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
-
- /* HorizontalTotal */
- vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
- /* HorizDisplayEnd */
- vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd);
- /* StartHorizRetrace */
- vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace);
- /* EndHorizRetrace */
- vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace);
- /* Overflow */
- vga_io_wcrt(0x07, par->vga_state.Overflow);
- /* StartVertRetrace */
- vga_io_wcrt(0x10, par->vga_state.StartVertRetrace);
- /* EndVertRetrace */
- vga_io_wcrt(0x11, par->vga_state.EndVertRetrace);
- /* ModeControl */
- vga_io_wcrt(0x17, par->vga_state.ModeControl);
- /* ClockingMode */
- vga_io_wseq(0x01, par->vga_state.ClockingMode);
-
- /* restore index/control registers */
- vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
- vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
-}
-
-static void vga_pal_blank(void)
-{
- int i;
-
- for (i=0; i<16; i++) {
- outb_p(i, VGA_PEL_IW);
- outb_p(0, VGA_PEL_D);
- outb_p(0, VGA_PEL_D);
- outb_p(0, VGA_PEL_D);
- }
-}
-
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-static int vga16fb_blank(int blank, struct fb_info *info)
-{
- struct vga16fb_par *par = info->par;
-
- switch (blank) {
- case FB_BLANK_UNBLANK: /* Unblank */
- if (par->vesa_blanked) {
- vga_vesa_unblank(par);
- par->vesa_blanked = 0;
- }
- if (par->palette_blanked) {
- par->palette_blanked = 0;
- }
- break;
- case FB_BLANK_NORMAL: /* blank */
- vga_pal_blank();
- par->palette_blanked = 1;
- break;
- default: /* VESA blanking */
- vga_vesa_blank(par, blank);
- par->vesa_blanked = 1;
- break;
- }
- return 0;
-}
-
-static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- u32 dx = rect->dx, width = rect->width;
- char oldindex = getindex();
- char oldmode = setmode(0x40);
- char oldmask = selectmask();
- int line_ofs, height;
- char oldop, oldsr;
- char __iomem *where;
-
- dx /= 4;
- where = info->screen_base + dx + rect->dy * info->fix.line_length;
-
- if (rect->rop == ROP_COPY) {
- oldop = setop(0);
- oldsr = setsr(0);
-
- width /= 4;
- line_ofs = info->fix.line_length - width;
- setmask(0xff);
-
- height = rect->height;
-
- while (height--) {
- int x;
-
- /* we can do memset... */
- for (x = width; x > 0; --x) {
- writeb(rect->color, where);
- where++;
- }
- where += line_ofs;
- }
- } else {
- char oldcolor = setcolor(0xf);
- int y;
-
- oldop = setop(0x18);
- oldsr = setsr(0xf);
- setmask(0x0F);
- for (y = 0; y < rect->height; y++) {
- rmw(where);
- rmw(where+1);
- where += info->fix.line_length;
- }
- setcolor(oldcolor);
- }
- setmask(oldmask);
- setsr(oldsr);
- setop(oldop);
- setmode(oldmode);
- setindex(oldindex);
-}
-
-static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- int x, x2, y2, vxres, vyres, width, height, line_ofs;
- char __iomem *dst;
-
- vxres = info->var.xres_virtual;
- vyres = info->var.yres_virtual;
-
- if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres)
- return;
-
- /* We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly. */
-
- x2 = rect->dx + rect->width;
- y2 = rect->dy + rect->height;
- x2 = x2 < vxres ? x2 : vxres;
- y2 = y2 < vyres ? y2 : vyres;
- width = x2 - rect->dx;
-
- switch (info->fix.type) {
- case FB_TYPE_VGA_PLANES:
- if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
-
- height = y2 - rect->dy;
- width = rect->width/8;
-
- line_ofs = info->fix.line_length - width;
- dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length;
-
- switch (rect->rop) {
- case ROP_COPY:
- setmode(0);
- setop(0);
- setsr(0xf);
- setcolor(rect->color);
- selectmask();
-
- setmask(0xff);
-
- while (height--) {
- for (x = 0; x < width; x++) {
- writeb(0, dst);
- dst++;
- }
- dst += line_ofs;
- }
- break;
- case ROP_XOR:
- setmode(0);
- setop(0x18);
- setsr(0xf);
- setcolor(0xf);
- selectmask();
-
- setmask(0xff);
- while (height--) {
- for (x = 0; x < width; x++) {
- rmw(dst);
- dst++;
- }
- dst += line_ofs;
- }
- break;
- }
- } else
- vga_8planes_fillrect(info, rect);
- break;
- case FB_TYPE_PACKED_PIXELS:
- default:
- cfb_fillrect(info, rect);
- break;
- }
-}
-
-static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
- char oldindex = getindex();
- char oldmode = setmode(0x41);
- char oldop = setop(0);
- char oldsr = setsr(0xf);
- int height, line_ofs, x;
- u32 sx, dx, width;
- char __iomem *dest;
- char __iomem *src;
-
- height = area->height;
-
- sx = area->sx / 4;
- dx = area->dx / 4;
- width = area->width / 4;
-
- if (area->dy < area->sy || (area->dy == area->sy && dx < sx)) {
- line_ofs = info->fix.line_length - width;
- dest = info->screen_base + dx + area->dy * info->fix.line_length;
- src = info->screen_base + sx + area->sy * info->fix.line_length;
- while (height--) {
- for (x = 0; x < width; x++) {
- readb(src);
- writeb(0, dest);
- src++;
- dest++;
- }
- src += line_ofs;
- dest += line_ofs;
- }
- } else {
- line_ofs = info->fix.line_length - width;
- dest = info->screen_base + dx + width +
- (area->dy + height - 1) * info->fix.line_length;
- src = info->screen_base + sx + width +
- (area->sy + height - 1) * info->fix.line_length;
- while (height--) {
- for (x = 0; x < width; x++) {
- --src;
- --dest;
- readb(src);
- writeb(0, dest);
- }
- src -= line_ofs;
- dest -= line_ofs;
- }
- }
-
- setsr(oldsr);
- setop(oldop);
- setmode(oldmode);
- setindex(oldindex);
-}
-
-static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
- u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
- int x, x2, y2, old_dx, old_dy, vxres, vyres;
- int height, width, line_ofs;
- char __iomem *dst = NULL;
- char __iomem *src = NULL;
-
- vxres = info->var.xres_virtual;
- vyres = info->var.yres_virtual;
-
- if (area->dx > vxres || area->sx > vxres || area->dy > vyres ||
- area->sy > vyres)
- return;
-
- /* clip the destination */
- old_dx = area->dx;
- old_dy = area->dy;
-
- /*
- * We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly.
- */
- x2 = area->dx + area->width;
- y2 = area->dy + area->height;
- dx = area->dx > 0 ? area->dx : 0;
- dy = area->dy > 0 ? area->dy : 0;
- x2 = x2 < vxres ? x2 : vxres;
- y2 = y2 < vyres ? y2 : vyres;
- width = x2 - dx;
- height = y2 - dy;
-
- if (sx + dx < old_dx || sy + dy < old_dy)
- return;
-
- /* update sx1,sy1 */
- sx += (dx - old_dx);
- sy += (dy - old_dy);
-
- /* the source must be completely inside the virtual screen */
- if (sx + width > vxres || sy + height > vyres)
- return;
-
- switch (info->fix.type) {
- case FB_TYPE_VGA_PLANES:
- if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
- width = width/8;
- line_ofs = info->fix.line_length - width;
-
- setmode(1);
- setop(0);
- setsr(0xf);
-
- if (dy < sy || (dy == sy && dx < sx)) {
- dst = info->screen_base + (dx/8) + dy * info->fix.line_length;
- src = info->screen_base + (sx/8) + sy * info->fix.line_length;
- while (height--) {
- for (x = 0; x < width; x++) {
- readb(src);
- writeb(0, dst);
- dst++;
- src++;
- }
- src += line_ofs;
- dst += line_ofs;
- }
- } else {
- dst = info->screen_base + (dx/8) + width +
- (dy + height - 1) * info->fix.line_length;
- src = info->screen_base + (sx/8) + width +
- (sy + height - 1) * info->fix.line_length;
- while (height--) {
- for (x = 0; x < width; x++) {
- dst--;
- src--;
- readb(src);
- writeb(0, dst);
- }
- src -= line_ofs;
- dst -= line_ofs;
- }
- }
- } else
- vga_8planes_copyarea(info, area);
- break;
- case FB_TYPE_PACKED_PIXELS:
- default:
- cfb_copyarea(info, area);
- break;
- }
-}
-
-#define TRANS_MASK_LOW {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
-#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
- 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
-
-#if defined(__LITTLE_ENDIAN)
-static const u16 transl_l[] = TRANS_MASK_LOW;
-static const u16 transl_h[] = TRANS_MASK_HIGH;
-#elif defined(__BIG_ENDIAN)
-static const u16 transl_l[] = TRANS_MASK_HIGH;
-static const u16 transl_h[] = TRANS_MASK_LOW;
-#else
-#error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
-#endif
-
-static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- char oldindex = getindex();
- char oldmode = setmode(0x40);
- char oldop = setop(0);
- char oldsr = setsr(0);
- char oldmask = selectmask();
- const unsigned char *cdat = image->data;
- u32 dx = image->dx;
- char __iomem *where;
- int y;
-
- dx /= 4;
- where = info->screen_base + dx + image->dy * info->fix.line_length;
-
- setmask(0xff);
- writeb(image->bg_color, where);
- readb(where);
- selectmask();
- setmask(image->fg_color ^ image->bg_color);
- setmode(0x42);
- setop(0x18);
- for (y = 0; y < image->height; y++, where += info->fix.line_length)
- writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where);
- setmask(oldmask);
- setsr(oldsr);
- setop(oldop);
- setmode(oldmode);
- setindex(oldindex);
-}
-
-static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
-{
- char __iomem *where = info->screen_base + (image->dx/8) +
- image->dy * info->fix.line_length;
- struct vga16fb_par *par = info->par;
- char *cdat = (char *) image->data;
- char __iomem *dst;
- int x, y;
-
- switch (info->fix.type) {
- case FB_TYPE_VGA_PLANES:
- if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
- if (par->isVGA) {
- setmode(2);
- setop(0);
- setsr(0xf);
- setcolor(image->fg_color);
- selectmask();
-
- setmask(0xff);
- writeb(image->bg_color, where);
- rmb();
- readb(where); /* fill latches */
- setmode(3);
- wmb();
- for (y = 0; y < image->height; y++) {
- dst = where;
- for (x = image->width/8; x--;)
- writeb(*cdat++, dst++);
- where += info->fix.line_length;
- }
- wmb();
- } else {
- setmode(0);
- setop(0);
- setsr(0xf);
- setcolor(image->bg_color);
- selectmask();
-
- setmask(0xff);
- for (y = 0; y < image->height; y++) {
- dst = where;
- for (x=image->width/8; x--;){
- rmw(dst);
- setcolor(image->fg_color);
- selectmask();
- if (*cdat) {
- setmask(*cdat++);
- rmw(dst++);
- }
- }
- where += info->fix.line_length;
- }
- }
- } else
- vga_8planes_imageblit(info, image);
- break;
- case FB_TYPE_PACKED_PIXELS:
- default:
- cfb_imageblit(info, image);
- break;
- }
-}
-
-static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
-{
- /*
- * Draw logo
- */
- struct vga16fb_par *par = info->par;
- char __iomem *where =
- info->screen_base + image->dy * info->fix.line_length +
- image->dx/8;
- const char *cdat = image->data;
- char __iomem *dst;
- int x, y;
-
- switch (info->fix.type) {
- case FB_TYPE_VGA_PLANES:
- if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 &&
- par->isVGA) {
- setsr(0xf);
- setop(0);
- setmode(0);
-
- for (y = 0; y < image->height; y++) {
- for (x = 0; x < image->width; x++) {
- dst = where + x/8;
-
- setcolor(*cdat);
- selectmask();
- setmask(1 << (7 - (x % 8)));
- fb_readb(dst);
- fb_writeb(0, dst);
-
- cdat++;
- }
- where += info->fix.line_length;
- }
- }
- break;
- case FB_TYPE_PACKED_PIXELS:
- cfb_imageblit(info, image);
- break;
- default:
- break;
- }
-}
-
-static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- if (image->depth == 1)
- vga_imageblit_expand(info, image);
- else
- vga_imageblit_color(info, image);
-}
-
-static void vga16fb_destroy(struct fb_info *info)
-{
- iounmap(info->screen_base);
- fb_dealloc_cmap(&info->cmap);
- /* XXX unshare VGA regions */
- framebuffer_release(info);
-}
-
-static const struct fb_ops vga16fb_ops = {
- .owner = THIS_MODULE,
- .fb_open = vga16fb_open,
- .fb_release = vga16fb_release,
- __FB_DEFAULT_IOMEM_OPS_RDWR,
- .fb_destroy = vga16fb_destroy,
- .fb_check_var = vga16fb_check_var,
- .fb_set_par = vga16fb_set_par,
- .fb_setcolreg = vga16fb_setcolreg,
- .fb_pan_display = vga16fb_pan_display,
- .fb_blank = vga16fb_blank,
- .fb_fillrect = vga16fb_fillrect,
- .fb_copyarea = vga16fb_copyarea,
- .fb_imageblit = vga16fb_imageblit,
- __FB_DEFAULT_IOMEM_OPS_MMAP,
-};
-
-static int vga16fb_probe(struct platform_device *dev)
-{
- struct sysfb_display_info *dpy;
- struct screen_info *si;
- struct fb_info *info;
- struct vga16fb_par *par;
- int i;
- int ret = 0;
-
- dpy = dev_get_platdata(&dev->dev);
- if (!dpy)
- return -ENODEV;
- si = &dpy->screen;
-
- ret = check_mode_supported(si);
- if (ret)
- return ret;
-
- dev_dbg(&dev->dev, "initializing\n");
- if (!request_mem_region(vga16fb_fix.smem_start, vga16fb_fix.smem_len,
- "vga16b")) {
- dev_err(&dev->dev, "cannot reserve video memory at 0x%lx\n",
- vga16fb_fix.smem_start);
- }
- info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);
-
- if (!info) {
- ret = -ENOMEM;
- goto err_fb_alloc;
- }
-
- /* XXX share VGA_FB_PHYS_BASE and I/O region with vgacon and others */
- info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS_BASE, 0);
-
- if (!info->screen_base) {
- dev_err(&dev->dev, "unable to map device\n");
- ret = -ENOMEM;
- goto err_ioremap;
- }
-
- dev_info(&dev->dev, "mapped to 0x%p\n", info->screen_base);
- par = info->par;
-
- par->isVGA = screen_info_video_type(si) == VIDEO_TYPE_VGAC;
- par->palette_blanked = 0;
- par->vesa_blanked = 0;
-
- i = par->isVGA? 6 : 2;
-
- vga16fb_defined.red.length = i;
- vga16fb_defined.green.length = i;
- vga16fb_defined.blue.length = i;
-
- /* name should not depend on EGA/VGA */
- info->fbops = &vga16fb_ops;
- info->var = vga16fb_defined;
- info->fix = vga16fb_fix;
- /* supports rectangles with widths of multiples of 8 */
- bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
- set_bit(8 - 1, info->pixmap.blit_x);
- set_bit(16 - 1, info->pixmap.blit_x);
- set_bit(24 - 1, info->pixmap.blit_x);
- set_bit(32 - 1, info->pixmap.blit_x);
- info->flags = FBINFO_HWACCEL_YPAN;
-
- i = (info->var.bits_per_pixel == 8) ? 256 : 16;
- ret = fb_alloc_cmap(&info->cmap, i, 0);
- if (ret) {
- dev_err(&dev->dev, "unable to allocate colormap\n");
- ret = -ENOMEM;
- goto err_alloc_cmap;
- }
-
- if (vga16fb_check_var(&info->var, info)) {
- dev_err(&dev->dev, "unable to validate variable\n");
- ret = -EINVAL;
- goto err_check_var;
- }
-
- vga16fb_update_fix(info);
-
- ret = devm_aperture_acquire_for_platform_device(dev, VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE);
- if (ret)
- goto err_check_var;
- if (register_framebuffer(info) < 0) {
- dev_err(&dev->dev, "unable to register framebuffer\n");
- ret = -EINVAL;
- goto err_check_var;
- }
-
- fb_info(info, "%s frame buffer device\n", info->fix.id);
- platform_set_drvdata(dev, info);
-
- return 0;
-
- err_check_var:
- fb_dealloc_cmap(&info->cmap);
- err_alloc_cmap:
- iounmap(info->screen_base);
- err_ioremap:
- framebuffer_release(info);
- err_fb_alloc:
- release_mem_region(vga16fb_fix.smem_start,
- vga16fb_fix.smem_len);
- return ret;
-}
-
-static void vga16fb_remove(struct platform_device *dev)
-{
- struct fb_info *info = platform_get_drvdata(dev);
-
- if (info)
- unregister_framebuffer(info);
- release_mem_region(vga16fb_fix.smem_start,
- vga16fb_fix.smem_len);
-}
-
-static const struct platform_device_id vga16fb_driver_id_table[] = {
- {"ega-framebuffer", 0},
- {"vga-framebuffer", 0},
- { }
-};
-MODULE_DEVICE_TABLE(platform, vga16fb_driver_id_table);
-
-static struct platform_driver vga16fb_driver = {
- .probe = vga16fb_probe,
- .remove = vga16fb_remove,
- .driver = {
- .name = "vga16fb",
- },
- .id_table = vga16fb_driver_id_table,
-};
-
-module_platform_driver(vga16fb_driver);
-
-MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
-MODULE_LICENSE("GPL");
--
2.54.0
next reply other threads:[~2026-06-13 3:31 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-13 3:31 Gabriel Ramos Barbosa Mota [this message]
2026-06-13 3:31 ` [PATCH] staging: vme_user: remove obsolete VMEbus driver and Kconfig entry Gabriel Ramos Barbosa Mota
2026-06-13 7:54 ` [PATCH] drivers: net and video: remove legacy 16-bit and non-x86 hardware drivers Andrew Lunn
-- strict thread matches above, loose matches on Subject: below --
2026-06-12 22:31 Gabriel Ramos Barbosa Mota
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260613033138.601841-1-maguraa53@gmail.com \
--to=maguraa53@gmail.com \
--cc=davem@davemloft.net \
--cc=deller@gmx.de \
--cc=dri-devel@lists.freedesktop.org \
--cc=fero@drama.obuda.kando.hu \
--cc=kuba@kernel.org \
--cc=linux-fbdev@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox