18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Linux ARCnet driver - COM20020 PCI support
38c2ecf20Sopenharmony_ci * Contemporary Controls PCI20 and SOHARD SH-ARC PCI
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Written 1994-1999 by Avery Pennarun,
68c2ecf20Sopenharmony_ci *    based on an ISA version by David Woodhouse.
78c2ecf20Sopenharmony_ci * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
88c2ecf20Sopenharmony_ci * Derived from skeleton.c by Donald Becker.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
118c2ecf20Sopenharmony_ci *  for sponsoring the further development of this driver.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * **********************
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * The original copyright of skeleton.c was as follows:
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * skeleton.c Written 1993 by Donald Becker.
188c2ecf20Sopenharmony_ci * Copyright 1993 United States Government as represented by the
198c2ecf20Sopenharmony_ci * Director, National Security Agency.  This software may only be used
208c2ecf20Sopenharmony_ci * and distributed according to the terms of the GNU General Public License as
218c2ecf20Sopenharmony_ci * modified by SRC, incorporated herein by reference.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * **********************
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * For more details, see drivers/net/arcnet.c
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * **********************
288c2ecf20Sopenharmony_ci */
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include <linux/module.h>
338c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
348c2ecf20Sopenharmony_ci#include <linux/kernel.h>
358c2ecf20Sopenharmony_ci#include <linux/types.h>
368c2ecf20Sopenharmony_ci#include <linux/ioport.h>
378c2ecf20Sopenharmony_ci#include <linux/errno.h>
388c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
398c2ecf20Sopenharmony_ci#include <linux/init.h>
408c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
418c2ecf20Sopenharmony_ci#include <linux/pci.h>
428c2ecf20Sopenharmony_ci#include <linux/list.h>
438c2ecf20Sopenharmony_ci#include <linux/io.h>
448c2ecf20Sopenharmony_ci#include <linux/leds.h>
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#include "arcdevice.h"
478c2ecf20Sopenharmony_ci#include "com20020.h"
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* Module parameters */
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic int node;
528c2ecf20Sopenharmony_cistatic char device[9];		/* use eg. device="arc1" to change name */
538c2ecf20Sopenharmony_cistatic int timeout = 3;
548c2ecf20Sopenharmony_cistatic int backplane;
558c2ecf20Sopenharmony_cistatic int clockp;
568c2ecf20Sopenharmony_cistatic int clockm;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cimodule_param(node, int, 0);
598c2ecf20Sopenharmony_cimodule_param_string(device, device, sizeof(device), 0);
608c2ecf20Sopenharmony_cimodule_param(timeout, int, 0);
618c2ecf20Sopenharmony_cimodule_param(backplane, int, 0);
628c2ecf20Sopenharmony_cimodule_param(clockp, int, 0);
638c2ecf20Sopenharmony_cimodule_param(clockm, int, 0);
648c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic void led_tx_set(struct led_classdev *led_cdev,
678c2ecf20Sopenharmony_ci			     enum led_brightness value)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	struct com20020_dev *card;
708c2ecf20Sopenharmony_ci	struct com20020_priv *priv;
718c2ecf20Sopenharmony_ci	struct com20020_pci_card_info *ci;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	card = container_of(led_cdev, struct com20020_dev, tx_led);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	priv = card->pci_priv;
768c2ecf20Sopenharmony_ci	ci = priv->ci;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	outb(!!value, priv->misc + ci->leds[card->index].green);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic void led_recon_set(struct led_classdev *led_cdev,
828c2ecf20Sopenharmony_ci			     enum led_brightness value)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	struct com20020_dev *card;
858c2ecf20Sopenharmony_ci	struct com20020_priv *priv;
868c2ecf20Sopenharmony_ci	struct com20020_pci_card_info *ci;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	card = container_of(led_cdev, struct com20020_dev, recon_led);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	priv = card->pci_priv;
918c2ecf20Sopenharmony_ci	ci = priv->ci;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	outb(!!value, priv->misc + ci->leds[card->index].red);
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistatic ssize_t backplane_mode_show(struct device *dev,
978c2ecf20Sopenharmony_ci				   struct device_attribute *attr,
988c2ecf20Sopenharmony_ci				   char *buf)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	struct net_device *net_dev = to_net_dev(dev);
1018c2ecf20Sopenharmony_ci	struct arcnet_local *lp = netdev_priv(net_dev);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", lp->backplane ? "true" : "false");
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(backplane_mode);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic struct attribute *com20020_state_attrs[] = {
1088c2ecf20Sopenharmony_ci	&dev_attr_backplane_mode.attr,
1098c2ecf20Sopenharmony_ci	NULL,
1108c2ecf20Sopenharmony_ci};
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic const struct attribute_group com20020_state_group = {
1138c2ecf20Sopenharmony_ci	.name = NULL,
1148c2ecf20Sopenharmony_ci	.attrs = com20020_state_attrs,
1158c2ecf20Sopenharmony_ci};
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic void com20020pci_remove(struct pci_dev *pdev);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic int com20020pci_probe(struct pci_dev *pdev,
1208c2ecf20Sopenharmony_ci			     const struct pci_device_id *id)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	struct com20020_pci_card_info *ci;
1238c2ecf20Sopenharmony_ci	struct com20020_pci_channel_map *mm;
1248c2ecf20Sopenharmony_ci	struct net_device *dev;
1258c2ecf20Sopenharmony_ci	struct arcnet_local *lp;
1268c2ecf20Sopenharmony_ci	struct com20020_priv *priv;
1278c2ecf20Sopenharmony_ci	int i, ioaddr, ret;
1288c2ecf20Sopenharmony_ci	struct resource *r;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	ret = 0;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	if (pci_enable_device(pdev))
1338c2ecf20Sopenharmony_ci		return -EIO;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
1368c2ecf20Sopenharmony_ci			    GFP_KERNEL);
1378c2ecf20Sopenharmony_ci	if (!priv)
1388c2ecf20Sopenharmony_ci		return -ENOMEM;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	ci = (struct com20020_pci_card_info *)id->driver_data;
1418c2ecf20Sopenharmony_ci	if (!ci)
1428c2ecf20Sopenharmony_ci		return -EINVAL;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	priv->ci = ci;
1458c2ecf20Sopenharmony_ci	mm = &ci->misc_map;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, priv);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&priv->list_dev);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	if (mm->size) {
1528c2ecf20Sopenharmony_ci		ioaddr = pci_resource_start(pdev, mm->bar) + mm->offset;
1538c2ecf20Sopenharmony_ci		r = devm_request_region(&pdev->dev, ioaddr, mm->size,
1548c2ecf20Sopenharmony_ci					"com20020-pci");
1558c2ecf20Sopenharmony_ci		if (!r) {
1568c2ecf20Sopenharmony_ci			pr_err("IO region %xh-%xh already allocated.\n",
1578c2ecf20Sopenharmony_ci			       ioaddr, ioaddr + mm->size - 1);
1588c2ecf20Sopenharmony_ci			return -EBUSY;
1598c2ecf20Sopenharmony_ci		}
1608c2ecf20Sopenharmony_ci		priv->misc = ioaddr;
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	for (i = 0; i < ci->devcount; i++) {
1648c2ecf20Sopenharmony_ci		struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
1658c2ecf20Sopenharmony_ci		struct com20020_dev *card;
1668c2ecf20Sopenharmony_ci		int dev_id_mask = 0xf;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci		dev = alloc_arcdev(device);
1698c2ecf20Sopenharmony_ci		if (!dev) {
1708c2ecf20Sopenharmony_ci			ret = -ENOMEM;
1718c2ecf20Sopenharmony_ci			break;
1728c2ecf20Sopenharmony_ci		}
1738c2ecf20Sopenharmony_ci		dev->dev_port = i;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		dev->netdev_ops = &com20020_netdev_ops;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci		lp = netdev_priv(dev);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci		arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
1808c2ecf20Sopenharmony_ci		ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci		r = devm_request_region(&pdev->dev, ioaddr, cm->size,
1838c2ecf20Sopenharmony_ci					"com20020-pci");
1848c2ecf20Sopenharmony_ci		if (!r) {
1858c2ecf20Sopenharmony_ci			pr_err("IO region %xh-%xh already allocated\n",
1868c2ecf20Sopenharmony_ci			       ioaddr, ioaddr + cm->size - 1);
1878c2ecf20Sopenharmony_ci			ret = -EBUSY;
1888c2ecf20Sopenharmony_ci			goto err_free_arcdev;
1898c2ecf20Sopenharmony_ci		}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci		/* Dummy access after Reset
1928c2ecf20Sopenharmony_ci		 * ARCNET controller needs
1938c2ecf20Sopenharmony_ci		 * this access to detect bustype
1948c2ecf20Sopenharmony_ci		 */
1958c2ecf20Sopenharmony_ci		arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
1968c2ecf20Sopenharmony_ci		arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci		SET_NETDEV_DEV(dev, &pdev->dev);
1998c2ecf20Sopenharmony_ci		dev->base_addr = ioaddr;
2008c2ecf20Sopenharmony_ci		dev->dev_addr[0] = node;
2018c2ecf20Sopenharmony_ci		dev->sysfs_groups[0] = &com20020_state_group;
2028c2ecf20Sopenharmony_ci		dev->irq = pdev->irq;
2038c2ecf20Sopenharmony_ci		lp->card_name = "PCI COM20020";
2048c2ecf20Sopenharmony_ci		lp->card_flags = ci->flags;
2058c2ecf20Sopenharmony_ci		lp->backplane = backplane;
2068c2ecf20Sopenharmony_ci		lp->clockp = clockp & 7;
2078c2ecf20Sopenharmony_ci		lp->clockm = clockm & 3;
2088c2ecf20Sopenharmony_ci		lp->timeout = timeout;
2098c2ecf20Sopenharmony_ci		lp->hw.owner = THIS_MODULE;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci		lp->backplane = (inb(priv->misc) >> (2 + i)) & 0x1;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci		if (!strncmp(ci->name, "EAE PLX-PCI FB2", 15))
2148c2ecf20Sopenharmony_ci			lp->backplane = 1;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci		if (ci->flags & ARC_HAS_ROTARY) {
2178c2ecf20Sopenharmony_ci			/* Get the dev_id from the PLX rotary coder */
2188c2ecf20Sopenharmony_ci			if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
2198c2ecf20Sopenharmony_ci				dev_id_mask = 0x3;
2208c2ecf20Sopenharmony_ci			dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
2218c2ecf20Sopenharmony_ci			snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
2228c2ecf20Sopenharmony_ci		}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci		if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
2258c2ecf20Sopenharmony_ci			pr_err("IO address %Xh is empty!\n", ioaddr);
2268c2ecf20Sopenharmony_ci			ret = -EIO;
2278c2ecf20Sopenharmony_ci			goto err_free_arcdev;
2288c2ecf20Sopenharmony_ci		}
2298c2ecf20Sopenharmony_ci		if (com20020_check(dev)) {
2308c2ecf20Sopenharmony_ci			ret = -EIO;
2318c2ecf20Sopenharmony_ci			goto err_free_arcdev;
2328c2ecf20Sopenharmony_ci		}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci		ret = com20020_found(dev, IRQF_SHARED);
2358c2ecf20Sopenharmony_ci		if (ret)
2368c2ecf20Sopenharmony_ci			goto err_free_arcdev;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci		card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
2398c2ecf20Sopenharmony_ci				    GFP_KERNEL);
2408c2ecf20Sopenharmony_ci		if (!card) {
2418c2ecf20Sopenharmony_ci			ret = -ENOMEM;
2428c2ecf20Sopenharmony_ci			goto err_free_arcdev;
2438c2ecf20Sopenharmony_ci		}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci		card->index = i;
2468c2ecf20Sopenharmony_ci		card->pci_priv = priv;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci		if (ci->flags & ARC_HAS_LED) {
2498c2ecf20Sopenharmony_ci			card->tx_led.brightness_set = led_tx_set;
2508c2ecf20Sopenharmony_ci			card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
2518c2ecf20Sopenharmony_ci							GFP_KERNEL, "arc%d-%d-tx",
2528c2ecf20Sopenharmony_ci							dev->dev_id, i);
2538c2ecf20Sopenharmony_ci			card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
2548c2ecf20Sopenharmony_ci							"pci:green:tx:%d-%d",
2558c2ecf20Sopenharmony_ci							dev->dev_id, i);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci			card->tx_led.dev = &dev->dev;
2588c2ecf20Sopenharmony_ci			card->recon_led.brightness_set = led_recon_set;
2598c2ecf20Sopenharmony_ci			card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
2608c2ecf20Sopenharmony_ci							GFP_KERNEL, "arc%d-%d-recon",
2618c2ecf20Sopenharmony_ci							dev->dev_id, i);
2628c2ecf20Sopenharmony_ci			card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
2638c2ecf20Sopenharmony_ci							"pci:red:recon:%d-%d",
2648c2ecf20Sopenharmony_ci							dev->dev_id, i);
2658c2ecf20Sopenharmony_ci			card->recon_led.dev = &dev->dev;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci			ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
2688c2ecf20Sopenharmony_ci			if (ret)
2698c2ecf20Sopenharmony_ci				goto err_free_arcdev;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci			ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
2728c2ecf20Sopenharmony_ci			if (ret)
2738c2ecf20Sopenharmony_ci				goto err_free_arcdev;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci			dev_set_drvdata(&dev->dev, card);
2768c2ecf20Sopenharmony_ci			devm_arcnet_led_init(dev, dev->dev_id, i);
2778c2ecf20Sopenharmony_ci		}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci		card->dev = dev;
2808c2ecf20Sopenharmony_ci		list_add(&card->list, &priv->list_dev);
2818c2ecf20Sopenharmony_ci		continue;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_cierr_free_arcdev:
2848c2ecf20Sopenharmony_ci		free_arcdev(dev);
2858c2ecf20Sopenharmony_ci		break;
2868c2ecf20Sopenharmony_ci	}
2878c2ecf20Sopenharmony_ci	if (ret)
2888c2ecf20Sopenharmony_ci		com20020pci_remove(pdev);
2898c2ecf20Sopenharmony_ci	return ret;
2908c2ecf20Sopenharmony_ci}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_cistatic void com20020pci_remove(struct pci_dev *pdev)
2938c2ecf20Sopenharmony_ci{
2948c2ecf20Sopenharmony_ci	struct com20020_dev *card, *tmpcard;
2958c2ecf20Sopenharmony_ci	struct com20020_priv *priv;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	priv = pci_get_drvdata(pdev);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
3008c2ecf20Sopenharmony_ci		struct net_device *dev = card->dev;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci		unregister_netdev(dev);
3038c2ecf20Sopenharmony_ci		free_irq(dev->irq, dev);
3048c2ecf20Sopenharmony_ci		free_arcdev(dev);
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic struct com20020_pci_card_info card_info_10mbit = {
3098c2ecf20Sopenharmony_ci	.name = "ARC-PCI",
3108c2ecf20Sopenharmony_ci	.devcount = 1,
3118c2ecf20Sopenharmony_ci	.chan_map_tbl = {
3128c2ecf20Sopenharmony_ci		{
3138c2ecf20Sopenharmony_ci			.bar = 2,
3148c2ecf20Sopenharmony_ci			.offset = 0x00,
3158c2ecf20Sopenharmony_ci			.size = 0x08,
3168c2ecf20Sopenharmony_ci		},
3178c2ecf20Sopenharmony_ci	},
3188c2ecf20Sopenharmony_ci	.flags = ARC_CAN_10MBIT,
3198c2ecf20Sopenharmony_ci};
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic struct com20020_pci_card_info card_info_5mbit = {
3228c2ecf20Sopenharmony_ci	.name = "ARC-PCI",
3238c2ecf20Sopenharmony_ci	.devcount = 1,
3248c2ecf20Sopenharmony_ci	.chan_map_tbl = {
3258c2ecf20Sopenharmony_ci		{
3268c2ecf20Sopenharmony_ci			.bar = 2,
3278c2ecf20Sopenharmony_ci			.offset = 0x00,
3288c2ecf20Sopenharmony_ci			.size = 0x08,
3298c2ecf20Sopenharmony_ci		},
3308c2ecf20Sopenharmony_ci	},
3318c2ecf20Sopenharmony_ci	.flags = ARC_IS_5MBIT,
3328c2ecf20Sopenharmony_ci};
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic struct com20020_pci_card_info card_info_sohard = {
3358c2ecf20Sopenharmony_ci	.name = "SOHARD SH ARC-PCI",
3368c2ecf20Sopenharmony_ci	.devcount = 1,
3378c2ecf20Sopenharmony_ci	/* SOHARD needs PCI base addr 4 */
3388c2ecf20Sopenharmony_ci	.chan_map_tbl = {
3398c2ecf20Sopenharmony_ci		{
3408c2ecf20Sopenharmony_ci			.bar = 4,
3418c2ecf20Sopenharmony_ci			.offset = 0x00,
3428c2ecf20Sopenharmony_ci			.size = 0x08
3438c2ecf20Sopenharmony_ci		},
3448c2ecf20Sopenharmony_ci	},
3458c2ecf20Sopenharmony_ci	.flags = ARC_CAN_10MBIT,
3468c2ecf20Sopenharmony_ci};
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_cistatic struct com20020_pci_card_info card_info_eae_arc1 = {
3498c2ecf20Sopenharmony_ci	.name = "EAE PLX-PCI ARC1",
3508c2ecf20Sopenharmony_ci	.devcount = 1,
3518c2ecf20Sopenharmony_ci	.chan_map_tbl = {
3528c2ecf20Sopenharmony_ci		{
3538c2ecf20Sopenharmony_ci			.bar = 2,
3548c2ecf20Sopenharmony_ci			.offset = 0x00,
3558c2ecf20Sopenharmony_ci			.size = 0x08,
3568c2ecf20Sopenharmony_ci		},
3578c2ecf20Sopenharmony_ci	},
3588c2ecf20Sopenharmony_ci	.misc_map = {
3598c2ecf20Sopenharmony_ci		.bar = 2,
3608c2ecf20Sopenharmony_ci		.offset = 0x10,
3618c2ecf20Sopenharmony_ci		.size = 0x04,
3628c2ecf20Sopenharmony_ci	},
3638c2ecf20Sopenharmony_ci	.leds = {
3648c2ecf20Sopenharmony_ci		{
3658c2ecf20Sopenharmony_ci			.green = 0x0,
3668c2ecf20Sopenharmony_ci			.red = 0x1,
3678c2ecf20Sopenharmony_ci		},
3688c2ecf20Sopenharmony_ci	},
3698c2ecf20Sopenharmony_ci	.rotary = 0x0,
3708c2ecf20Sopenharmony_ci	.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
3718c2ecf20Sopenharmony_ci};
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic struct com20020_pci_card_info card_info_eae_ma1 = {
3748c2ecf20Sopenharmony_ci	.name = "EAE PLX-PCI MA1",
3758c2ecf20Sopenharmony_ci	.devcount = 2,
3768c2ecf20Sopenharmony_ci	.chan_map_tbl = {
3778c2ecf20Sopenharmony_ci		{
3788c2ecf20Sopenharmony_ci			.bar = 2,
3798c2ecf20Sopenharmony_ci			.offset = 0x00,
3808c2ecf20Sopenharmony_ci			.size = 0x08,
3818c2ecf20Sopenharmony_ci		}, {
3828c2ecf20Sopenharmony_ci			.bar = 2,
3838c2ecf20Sopenharmony_ci			.offset = 0x08,
3848c2ecf20Sopenharmony_ci			.size = 0x08,
3858c2ecf20Sopenharmony_ci		}
3868c2ecf20Sopenharmony_ci	},
3878c2ecf20Sopenharmony_ci	.misc_map = {
3888c2ecf20Sopenharmony_ci		.bar = 2,
3898c2ecf20Sopenharmony_ci		.offset = 0x10,
3908c2ecf20Sopenharmony_ci		.size = 0x04,
3918c2ecf20Sopenharmony_ci	},
3928c2ecf20Sopenharmony_ci	.leds = {
3938c2ecf20Sopenharmony_ci		{
3948c2ecf20Sopenharmony_ci			.green = 0x0,
3958c2ecf20Sopenharmony_ci			.red = 0x1,
3968c2ecf20Sopenharmony_ci		}, {
3978c2ecf20Sopenharmony_ci			.green = 0x2,
3988c2ecf20Sopenharmony_ci			.red = 0x3,
3998c2ecf20Sopenharmony_ci		},
4008c2ecf20Sopenharmony_ci	},
4018c2ecf20Sopenharmony_ci	.rotary = 0x0,
4028c2ecf20Sopenharmony_ci	.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
4038c2ecf20Sopenharmony_ci};
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic struct com20020_pci_card_info card_info_eae_fb2 = {
4068c2ecf20Sopenharmony_ci	.name = "EAE PLX-PCI FB2",
4078c2ecf20Sopenharmony_ci	.devcount = 1,
4088c2ecf20Sopenharmony_ci	.chan_map_tbl = {
4098c2ecf20Sopenharmony_ci		{
4108c2ecf20Sopenharmony_ci			.bar = 2,
4118c2ecf20Sopenharmony_ci			.offset = 0x00,
4128c2ecf20Sopenharmony_ci			.size = 0x08,
4138c2ecf20Sopenharmony_ci		},
4148c2ecf20Sopenharmony_ci	},
4158c2ecf20Sopenharmony_ci	.misc_map = {
4168c2ecf20Sopenharmony_ci		.bar = 2,
4178c2ecf20Sopenharmony_ci		.offset = 0x10,
4188c2ecf20Sopenharmony_ci		.size = 0x04,
4198c2ecf20Sopenharmony_ci	},
4208c2ecf20Sopenharmony_ci	.leds = {
4218c2ecf20Sopenharmony_ci		{
4228c2ecf20Sopenharmony_ci			.green = 0x0,
4238c2ecf20Sopenharmony_ci			.red = 0x1,
4248c2ecf20Sopenharmony_ci		},
4258c2ecf20Sopenharmony_ci	},
4268c2ecf20Sopenharmony_ci	.rotary = 0x0,
4278c2ecf20Sopenharmony_ci	.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
4288c2ecf20Sopenharmony_ci};
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_cistatic const struct pci_device_id com20020pci_id_table[] = {
4318c2ecf20Sopenharmony_ci	{
4328c2ecf20Sopenharmony_ci		0x1571, 0xa001,
4338c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4348c2ecf20Sopenharmony_ci		0, 0,
4358c2ecf20Sopenharmony_ci		0,
4368c2ecf20Sopenharmony_ci	},
4378c2ecf20Sopenharmony_ci	{
4388c2ecf20Sopenharmony_ci		0x1571, 0xa002,
4398c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4408c2ecf20Sopenharmony_ci		0, 0,
4418c2ecf20Sopenharmony_ci		0,
4428c2ecf20Sopenharmony_ci	},
4438c2ecf20Sopenharmony_ci	{
4448c2ecf20Sopenharmony_ci		0x1571, 0xa003,
4458c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4468c2ecf20Sopenharmony_ci		0, 0,
4478c2ecf20Sopenharmony_ci		0
4488c2ecf20Sopenharmony_ci	},
4498c2ecf20Sopenharmony_ci	{
4508c2ecf20Sopenharmony_ci		0x1571, 0xa004,
4518c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4528c2ecf20Sopenharmony_ci		0, 0,
4538c2ecf20Sopenharmony_ci		0,
4548c2ecf20Sopenharmony_ci	},
4558c2ecf20Sopenharmony_ci	{
4568c2ecf20Sopenharmony_ci		0x1571, 0xa005,
4578c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4588c2ecf20Sopenharmony_ci		0, 0,
4598c2ecf20Sopenharmony_ci		0
4608c2ecf20Sopenharmony_ci	},
4618c2ecf20Sopenharmony_ci	{
4628c2ecf20Sopenharmony_ci		0x1571, 0xa006,
4638c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4648c2ecf20Sopenharmony_ci		0, 0,
4658c2ecf20Sopenharmony_ci		0
4668c2ecf20Sopenharmony_ci	},
4678c2ecf20Sopenharmony_ci	{
4688c2ecf20Sopenharmony_ci		0x1571, 0xa007,
4698c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4708c2ecf20Sopenharmony_ci		0, 0,
4718c2ecf20Sopenharmony_ci		0
4728c2ecf20Sopenharmony_ci	},
4738c2ecf20Sopenharmony_ci	{
4748c2ecf20Sopenharmony_ci		0x1571, 0xa008,
4758c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4768c2ecf20Sopenharmony_ci		0, 0,
4778c2ecf20Sopenharmony_ci		0
4788c2ecf20Sopenharmony_ci	},
4798c2ecf20Sopenharmony_ci	{
4808c2ecf20Sopenharmony_ci		0x1571, 0xa009,
4818c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4828c2ecf20Sopenharmony_ci		0, 0,
4838c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_5mbit
4848c2ecf20Sopenharmony_ci	},
4858c2ecf20Sopenharmony_ci	{
4868c2ecf20Sopenharmony_ci		0x1571, 0xa00a,
4878c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4888c2ecf20Sopenharmony_ci		0, 0,
4898c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_5mbit
4908c2ecf20Sopenharmony_ci	},
4918c2ecf20Sopenharmony_ci	{
4928c2ecf20Sopenharmony_ci		0x1571, 0xa00b,
4938c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
4948c2ecf20Sopenharmony_ci		0, 0,
4958c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_5mbit
4968c2ecf20Sopenharmony_ci	},
4978c2ecf20Sopenharmony_ci	{
4988c2ecf20Sopenharmony_ci		0x1571, 0xa00c,
4998c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5008c2ecf20Sopenharmony_ci		0, 0,
5018c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_5mbit
5028c2ecf20Sopenharmony_ci	},
5038c2ecf20Sopenharmony_ci	{
5048c2ecf20Sopenharmony_ci		0x1571, 0xa00d,
5058c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5068c2ecf20Sopenharmony_ci		0, 0,
5078c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_5mbit
5088c2ecf20Sopenharmony_ci	},
5098c2ecf20Sopenharmony_ci	{
5108c2ecf20Sopenharmony_ci		0x1571, 0xa00e,
5118c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5128c2ecf20Sopenharmony_ci		0, 0,
5138c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_5mbit
5148c2ecf20Sopenharmony_ci	},
5158c2ecf20Sopenharmony_ci	{
5168c2ecf20Sopenharmony_ci		0x1571, 0xa201,
5178c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5188c2ecf20Sopenharmony_ci		0, 0,
5198c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_10mbit
5208c2ecf20Sopenharmony_ci	},
5218c2ecf20Sopenharmony_ci	{
5228c2ecf20Sopenharmony_ci		0x1571, 0xa202,
5238c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5248c2ecf20Sopenharmony_ci		0, 0,
5258c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_10mbit
5268c2ecf20Sopenharmony_ci	},
5278c2ecf20Sopenharmony_ci	{
5288c2ecf20Sopenharmony_ci		0x1571, 0xa203,
5298c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5308c2ecf20Sopenharmony_ci		0, 0,
5318c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_10mbit
5328c2ecf20Sopenharmony_ci	},
5338c2ecf20Sopenharmony_ci	{
5348c2ecf20Sopenharmony_ci		0x1571, 0xa204,
5358c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5368c2ecf20Sopenharmony_ci		0, 0,
5378c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_10mbit
5388c2ecf20Sopenharmony_ci	},
5398c2ecf20Sopenharmony_ci	{
5408c2ecf20Sopenharmony_ci		0x1571, 0xa205,
5418c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5428c2ecf20Sopenharmony_ci		0, 0,
5438c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_10mbit
5448c2ecf20Sopenharmony_ci	},
5458c2ecf20Sopenharmony_ci	{
5468c2ecf20Sopenharmony_ci		0x1571, 0xa206,
5478c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5488c2ecf20Sopenharmony_ci		0, 0,
5498c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_10mbit
5508c2ecf20Sopenharmony_ci	},
5518c2ecf20Sopenharmony_ci	{
5528c2ecf20Sopenharmony_ci		0x10B5, 0x9030,
5538c2ecf20Sopenharmony_ci		0x10B5, 0x2978,
5548c2ecf20Sopenharmony_ci		0, 0,
5558c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_sohard
5568c2ecf20Sopenharmony_ci	},
5578c2ecf20Sopenharmony_ci	{
5588c2ecf20Sopenharmony_ci		0x10B5, 0x9050,
5598c2ecf20Sopenharmony_ci		0x10B5, 0x2273,
5608c2ecf20Sopenharmony_ci		0, 0,
5618c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_sohard
5628c2ecf20Sopenharmony_ci	},
5638c2ecf20Sopenharmony_ci	{
5648c2ecf20Sopenharmony_ci		0x10B5, 0x9050,
5658c2ecf20Sopenharmony_ci		0x10B5, 0x3263,
5668c2ecf20Sopenharmony_ci		0, 0,
5678c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_eae_arc1
5688c2ecf20Sopenharmony_ci	},
5698c2ecf20Sopenharmony_ci	{
5708c2ecf20Sopenharmony_ci		0x10B5, 0x9050,
5718c2ecf20Sopenharmony_ci		0x10B5, 0x3292,
5728c2ecf20Sopenharmony_ci		0, 0,
5738c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_eae_ma1
5748c2ecf20Sopenharmony_ci	},
5758c2ecf20Sopenharmony_ci	{
5768c2ecf20Sopenharmony_ci		0x10B5, 0x9050,
5778c2ecf20Sopenharmony_ci		0x10B5, 0x3294,
5788c2ecf20Sopenharmony_ci		0, 0,
5798c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_eae_fb2
5808c2ecf20Sopenharmony_ci	},
5818c2ecf20Sopenharmony_ci	{
5828c2ecf20Sopenharmony_ci		0x14BA, 0x6000,
5838c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5848c2ecf20Sopenharmony_ci		0, 0,
5858c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_10mbit
5868c2ecf20Sopenharmony_ci	},
5878c2ecf20Sopenharmony_ci	{
5888c2ecf20Sopenharmony_ci		0x10B5, 0x2200,
5898c2ecf20Sopenharmony_ci		PCI_ANY_ID, PCI_ANY_ID,
5908c2ecf20Sopenharmony_ci		0, 0,
5918c2ecf20Sopenharmony_ci		(kernel_ulong_t)&card_info_10mbit
5928c2ecf20Sopenharmony_ci	},
5938c2ecf20Sopenharmony_ci	{ 0, }
5948c2ecf20Sopenharmony_ci};
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, com20020pci_id_table);
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic struct pci_driver com20020pci_driver = {
5998c2ecf20Sopenharmony_ci	.name		= "com20020",
6008c2ecf20Sopenharmony_ci	.id_table	= com20020pci_id_table,
6018c2ecf20Sopenharmony_ci	.probe		= com20020pci_probe,
6028c2ecf20Sopenharmony_ci	.remove		= com20020pci_remove,
6038c2ecf20Sopenharmony_ci};
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_cistatic int __init com20020pci_init(void)
6068c2ecf20Sopenharmony_ci{
6078c2ecf20Sopenharmony_ci	if (BUGLVL(D_NORMAL))
6088c2ecf20Sopenharmony_ci		pr_info("%s\n", "COM20020 PCI support");
6098c2ecf20Sopenharmony_ci	return pci_register_driver(&com20020pci_driver);
6108c2ecf20Sopenharmony_ci}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_cistatic void __exit com20020pci_cleanup(void)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	pci_unregister_driver(&com20020pci_driver);
6158c2ecf20Sopenharmony_ci}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_cimodule_init(com20020pci_init)
6188c2ecf20Sopenharmony_cimodule_exit(com20020pci_cleanup)
619