cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

com20020-pci.c (12267B)


      1/*
      2 * Linux ARCnet driver - COM20020 PCI support
      3 * Contemporary Controls PCI20 and SOHARD SH-ARC PCI
      4 *
      5 * Written 1994-1999 by Avery Pennarun,
      6 *    based on an ISA version by David Woodhouse.
      7 * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
      8 * Derived from skeleton.c by Donald Becker.
      9 *
     10 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
     11 *  for sponsoring the further development of this driver.
     12 *
     13 * **********************
     14 *
     15 * The original copyright of skeleton.c was as follows:
     16 *
     17 * skeleton.c Written 1993 by Donald Becker.
     18 * Copyright 1993 United States Government as represented by the
     19 * Director, National Security Agency.  This software may only be used
     20 * and distributed according to the terms of the GNU General Public License as
     21 * modified by SRC, incorporated herein by reference.
     22 *
     23 * **********************
     24 *
     25 * For more details, see drivers/net/arcnet.c
     26 *
     27 * **********************
     28 */
     29
     30#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
     31
     32#include <linux/module.h>
     33#include <linux/moduleparam.h>
     34#include <linux/kernel.h>
     35#include <linux/types.h>
     36#include <linux/ioport.h>
     37#include <linux/errno.h>
     38#include <linux/netdevice.h>
     39#include <linux/init.h>
     40#include <linux/interrupt.h>
     41#include <linux/pci.h>
     42#include <linux/list.h>
     43#include <linux/io.h>
     44#include <linux/leds.h>
     45
     46#include "arcdevice.h"
     47#include "com20020.h"
     48
     49/* Module parameters */
     50
     51static int node;
     52static char device[9];		/* use eg. device="arc1" to change name */
     53static int timeout = 3;
     54static int backplane;
     55static int clockp;
     56static int clockm;
     57
     58module_param(node, int, 0);
     59module_param_string(device, device, sizeof(device), 0);
     60module_param(timeout, int, 0);
     61module_param(backplane, int, 0);
     62module_param(clockp, int, 0);
     63module_param(clockm, int, 0);
     64MODULE_LICENSE("GPL");
     65
     66static void led_tx_set(struct led_classdev *led_cdev,
     67			     enum led_brightness value)
     68{
     69	struct com20020_dev *card;
     70	struct com20020_priv *priv;
     71	struct com20020_pci_card_info *ci;
     72
     73	card = container_of(led_cdev, struct com20020_dev, tx_led);
     74
     75	priv = card->pci_priv;
     76	ci = priv->ci;
     77
     78	outb(!!value, priv->misc + ci->leds[card->index].green);
     79}
     80
     81static void led_recon_set(struct led_classdev *led_cdev,
     82			     enum led_brightness value)
     83{
     84	struct com20020_dev *card;
     85	struct com20020_priv *priv;
     86	struct com20020_pci_card_info *ci;
     87
     88	card = container_of(led_cdev, struct com20020_dev, recon_led);
     89
     90	priv = card->pci_priv;
     91	ci = priv->ci;
     92
     93	outb(!!value, priv->misc + ci->leds[card->index].red);
     94}
     95
     96static ssize_t backplane_mode_show(struct device *dev,
     97				   struct device_attribute *attr,
     98				   char *buf)
     99{
    100	struct net_device *net_dev = to_net_dev(dev);
    101	struct arcnet_local *lp = netdev_priv(net_dev);
    102
    103	return sprintf(buf, "%s\n", lp->backplane ? "true" : "false");
    104}
    105static DEVICE_ATTR_RO(backplane_mode);
    106
    107static struct attribute *com20020_state_attrs[] = {
    108	&dev_attr_backplane_mode.attr,
    109	NULL,
    110};
    111
    112static const struct attribute_group com20020_state_group = {
    113	.name = NULL,
    114	.attrs = com20020_state_attrs,
    115};
    116
    117static void com20020pci_remove(struct pci_dev *pdev);
    118
    119static int com20020pci_probe(struct pci_dev *pdev,
    120			     const struct pci_device_id *id)
    121{
    122	struct com20020_pci_card_info *ci;
    123	struct com20020_pci_channel_map *mm;
    124	struct net_device *dev;
    125	struct arcnet_local *lp;
    126	struct com20020_priv *priv;
    127	int i, ioaddr, ret;
    128	struct resource *r;
    129
    130	ret = 0;
    131
    132	if (pci_enable_device(pdev))
    133		return -EIO;
    134
    135	priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
    136			    GFP_KERNEL);
    137	if (!priv)
    138		return -ENOMEM;
    139
    140	ci = (struct com20020_pci_card_info *)id->driver_data;
    141	if (!ci)
    142		return -EINVAL;
    143
    144	priv->ci = ci;
    145	mm = &ci->misc_map;
    146
    147	pci_set_drvdata(pdev, priv);
    148
    149	INIT_LIST_HEAD(&priv->list_dev);
    150
    151	if (mm->size) {
    152		ioaddr = pci_resource_start(pdev, mm->bar) + mm->offset;
    153		r = devm_request_region(&pdev->dev, ioaddr, mm->size,
    154					"com20020-pci");
    155		if (!r) {
    156			pr_err("IO region %xh-%xh already allocated.\n",
    157			       ioaddr, ioaddr + mm->size - 1);
    158			return -EBUSY;
    159		}
    160		priv->misc = ioaddr;
    161	}
    162
    163	for (i = 0; i < ci->devcount; i++) {
    164		struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
    165		struct com20020_dev *card;
    166		int dev_id_mask = 0xf;
    167
    168		dev = alloc_arcdev(device);
    169		if (!dev) {
    170			ret = -ENOMEM;
    171			break;
    172		}
    173		dev->dev_port = i;
    174
    175		dev->netdev_ops = &com20020_netdev_ops;
    176
    177		lp = netdev_priv(dev);
    178
    179		arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
    180		ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
    181
    182		r = devm_request_region(&pdev->dev, ioaddr, cm->size,
    183					"com20020-pci");
    184		if (!r) {
    185			pr_err("IO region %xh-%xh already allocated\n",
    186			       ioaddr, ioaddr + cm->size - 1);
    187			ret = -EBUSY;
    188			goto err_free_arcdev;
    189		}
    190
    191		/* Dummy access after Reset
    192		 * ARCNET controller needs
    193		 * this access to detect bustype
    194		 */
    195		arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
    196		arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
    197
    198		SET_NETDEV_DEV(dev, &pdev->dev);
    199		dev->base_addr = ioaddr;
    200		arcnet_set_addr(dev, node);
    201		dev->sysfs_groups[0] = &com20020_state_group;
    202		dev->irq = pdev->irq;
    203		lp->card_name = "PCI COM20020";
    204		lp->card_flags = ci->flags;
    205		lp->backplane = backplane;
    206		lp->clockp = clockp & 7;
    207		lp->clockm = clockm & 3;
    208		lp->timeout = timeout;
    209		lp->hw.owner = THIS_MODULE;
    210
    211		lp->backplane = (inb(priv->misc) >> (2 + i)) & 0x1;
    212
    213		if (!strncmp(ci->name, "EAE PLX-PCI FB2", 15))
    214			lp->backplane = 1;
    215
    216		/* Get the dev_id from the PLX rotary coder */
    217		if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
    218			dev_id_mask = 0x3;
    219		dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
    220
    221		snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
    222
    223		if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
    224			pr_err("IO address %Xh is empty!\n", ioaddr);
    225			ret = -EIO;
    226			goto err_free_arcdev;
    227		}
    228		if (com20020_check(dev)) {
    229			ret = -EIO;
    230			goto err_free_arcdev;
    231		}
    232
    233		card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
    234				    GFP_KERNEL);
    235		if (!card) {
    236			ret = -ENOMEM;
    237			goto err_free_arcdev;
    238		}
    239
    240		card->index = i;
    241		card->pci_priv = priv;
    242		card->tx_led.brightness_set = led_tx_set;
    243		card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
    244						GFP_KERNEL, "arc%d-%d-tx",
    245						dev->dev_id, i);
    246		card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
    247						"pci:green:tx:%d-%d",
    248						dev->dev_id, i);
    249
    250		card->tx_led.dev = &dev->dev;
    251		card->recon_led.brightness_set = led_recon_set;
    252		card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
    253						GFP_KERNEL, "arc%d-%d-recon",
    254						dev->dev_id, i);
    255		card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
    256						"pci:red:recon:%d-%d",
    257						dev->dev_id, i);
    258		card->recon_led.dev = &dev->dev;
    259		card->dev = dev;
    260
    261		ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
    262		if (ret)
    263			goto err_free_arcdev;
    264
    265		ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
    266		if (ret)
    267			goto err_free_arcdev;
    268
    269		dev_set_drvdata(&dev->dev, card);
    270
    271		ret = com20020_found(dev, IRQF_SHARED);
    272		if (ret)
    273			goto err_free_arcdev;
    274
    275		devm_arcnet_led_init(dev, dev->dev_id, i);
    276
    277		list_add(&card->list, &priv->list_dev);
    278		continue;
    279
    280err_free_arcdev:
    281		free_arcdev(dev);
    282		break;
    283	}
    284	if (ret)
    285		com20020pci_remove(pdev);
    286	return ret;
    287}
    288
    289static void com20020pci_remove(struct pci_dev *pdev)
    290{
    291	struct com20020_dev *card, *tmpcard;
    292	struct com20020_priv *priv;
    293
    294	priv = pci_get_drvdata(pdev);
    295
    296	list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
    297		struct net_device *dev = card->dev;
    298
    299		unregister_netdev(dev);
    300		free_irq(dev->irq, dev);
    301		free_arcdev(dev);
    302	}
    303}
    304
    305static struct com20020_pci_card_info card_info_10mbit = {
    306	.name = "ARC-PCI",
    307	.devcount = 1,
    308	.chan_map_tbl = {
    309		{
    310			.bar = 2,
    311			.offset = 0x00,
    312			.size = 0x08,
    313		},
    314	},
    315	.flags = ARC_CAN_10MBIT,
    316};
    317
    318static struct com20020_pci_card_info card_info_5mbit = {
    319	.name = "ARC-PCI",
    320	.devcount = 1,
    321	.chan_map_tbl = {
    322		{
    323			.bar = 2,
    324			.offset = 0x00,
    325			.size = 0x08,
    326		},
    327	},
    328	.flags = ARC_IS_5MBIT,
    329};
    330
    331static struct com20020_pci_card_info card_info_sohard = {
    332	.name = "PLX-PCI",
    333	.devcount = 1,
    334	/* SOHARD needs PCI base addr 4 */
    335	.chan_map_tbl = {
    336		{
    337			.bar = 4,
    338			.offset = 0x00,
    339			.size = 0x08
    340		},
    341	},
    342	.flags = ARC_CAN_10MBIT,
    343};
    344
    345static struct com20020_pci_card_info card_info_eae_arc1 = {
    346	.name = "EAE PLX-PCI ARC1",
    347	.devcount = 1,
    348	.chan_map_tbl = {
    349		{
    350			.bar = 2,
    351			.offset = 0x00,
    352			.size = 0x08,
    353		},
    354	},
    355	.misc_map = {
    356		.bar = 2,
    357		.offset = 0x10,
    358		.size = 0x04,
    359	},
    360	.leds = {
    361		{
    362			.green = 0x0,
    363			.red = 0x1,
    364		},
    365	},
    366	.rotary = 0x0,
    367	.flags = ARC_CAN_10MBIT,
    368};
    369
    370static struct com20020_pci_card_info card_info_eae_ma1 = {
    371	.name = "EAE PLX-PCI MA1",
    372	.devcount = 2,
    373	.chan_map_tbl = {
    374		{
    375			.bar = 2,
    376			.offset = 0x00,
    377			.size = 0x08,
    378		}, {
    379			.bar = 2,
    380			.offset = 0x08,
    381			.size = 0x08,
    382		}
    383	},
    384	.misc_map = {
    385		.bar = 2,
    386		.offset = 0x10,
    387		.size = 0x04,
    388	},
    389	.leds = {
    390		{
    391			.green = 0x0,
    392			.red = 0x1,
    393		}, {
    394			.green = 0x2,
    395			.red = 0x3,
    396		},
    397	},
    398	.rotary = 0x0,
    399	.flags = ARC_CAN_10MBIT,
    400};
    401
    402static struct com20020_pci_card_info card_info_eae_fb2 = {
    403	.name = "EAE PLX-PCI FB2",
    404	.devcount = 1,
    405	.chan_map_tbl = {
    406		{
    407			.bar = 2,
    408			.offset = 0x00,
    409			.size = 0x08,
    410		},
    411	},
    412	.misc_map = {
    413		.bar = 2,
    414		.offset = 0x10,
    415		.size = 0x04,
    416	},
    417	.leds = {
    418		{
    419			.green = 0x0,
    420			.red = 0x1,
    421		},
    422	},
    423	.rotary = 0x0,
    424	.flags = ARC_CAN_10MBIT,
    425};
    426
    427static const struct pci_device_id com20020pci_id_table[] = {
    428	{
    429		0x1571, 0xa001,
    430		PCI_ANY_ID, PCI_ANY_ID,
    431		0, 0,
    432		0,
    433	},
    434	{
    435		0x1571, 0xa002,
    436		PCI_ANY_ID, PCI_ANY_ID,
    437		0, 0,
    438		0,
    439	},
    440	{
    441		0x1571, 0xa003,
    442		PCI_ANY_ID, PCI_ANY_ID,
    443		0, 0,
    444		0
    445	},
    446	{
    447		0x1571, 0xa004,
    448		PCI_ANY_ID, PCI_ANY_ID,
    449		0, 0,
    450		0,
    451	},
    452	{
    453		0x1571, 0xa005,
    454		PCI_ANY_ID, PCI_ANY_ID,
    455		0, 0,
    456		0
    457	},
    458	{
    459		0x1571, 0xa006,
    460		PCI_ANY_ID, PCI_ANY_ID,
    461		0, 0,
    462		0
    463	},
    464	{
    465		0x1571, 0xa007,
    466		PCI_ANY_ID, PCI_ANY_ID,
    467		0, 0,
    468		0
    469	},
    470	{
    471		0x1571, 0xa008,
    472		PCI_ANY_ID, PCI_ANY_ID,
    473		0, 0,
    474		0
    475	},
    476	{
    477		0x1571, 0xa009,
    478		PCI_ANY_ID, PCI_ANY_ID,
    479		0, 0,
    480		(kernel_ulong_t)&card_info_5mbit
    481	},
    482	{
    483		0x1571, 0xa00a,
    484		PCI_ANY_ID, PCI_ANY_ID,
    485		0, 0,
    486		(kernel_ulong_t)&card_info_5mbit
    487	},
    488	{
    489		0x1571, 0xa00b,
    490		PCI_ANY_ID, PCI_ANY_ID,
    491		0, 0,
    492		(kernel_ulong_t)&card_info_5mbit
    493	},
    494	{
    495		0x1571, 0xa00c,
    496		PCI_ANY_ID, PCI_ANY_ID,
    497		0, 0,
    498		(kernel_ulong_t)&card_info_5mbit
    499	},
    500	{
    501		0x1571, 0xa00d,
    502		PCI_ANY_ID, PCI_ANY_ID,
    503		0, 0,
    504		(kernel_ulong_t)&card_info_5mbit
    505	},
    506	{
    507		0x1571, 0xa00e,
    508		PCI_ANY_ID, PCI_ANY_ID,
    509		0, 0,
    510		(kernel_ulong_t)&card_info_5mbit
    511	},
    512	{
    513		0x1571, 0xa201,
    514		PCI_ANY_ID, PCI_ANY_ID,
    515		0, 0,
    516		(kernel_ulong_t)&card_info_10mbit
    517	},
    518	{
    519		0x1571, 0xa202,
    520		PCI_ANY_ID, PCI_ANY_ID,
    521		0, 0,
    522		(kernel_ulong_t)&card_info_10mbit
    523	},
    524	{
    525		0x1571, 0xa203,
    526		PCI_ANY_ID, PCI_ANY_ID,
    527		0, 0,
    528		(kernel_ulong_t)&card_info_10mbit
    529	},
    530	{
    531		0x1571, 0xa204,
    532		PCI_ANY_ID, PCI_ANY_ID,
    533		0, 0,
    534		(kernel_ulong_t)&card_info_10mbit
    535	},
    536	{
    537		0x1571, 0xa205,
    538		PCI_ANY_ID, PCI_ANY_ID,
    539		0, 0,
    540		(kernel_ulong_t)&card_info_10mbit
    541	},
    542	{
    543		0x1571, 0xa206,
    544		PCI_ANY_ID, PCI_ANY_ID,
    545		0, 0,
    546		(kernel_ulong_t)&card_info_10mbit
    547	},
    548	{
    549		0x10B5, 0x9030,
    550		0x10B5, 0x2978,
    551		0, 0,
    552		(kernel_ulong_t)&card_info_sohard
    553	},
    554	{
    555		0x10B5, 0x9050,
    556		0x10B5, 0x2273,
    557		0, 0,
    558		(kernel_ulong_t)&card_info_sohard
    559	},
    560	{
    561		0x10B5, 0x9050,
    562		0x10B5, 0x3263,
    563		0, 0,
    564		(kernel_ulong_t)&card_info_eae_arc1
    565	},
    566	{
    567		0x10B5, 0x9050,
    568		0x10B5, 0x3292,
    569		0, 0,
    570		(kernel_ulong_t)&card_info_eae_ma1
    571	},
    572	{
    573		0x10B5, 0x9050,
    574		0x10B5, 0x3294,
    575		0, 0,
    576		(kernel_ulong_t)&card_info_eae_fb2
    577	},
    578	{
    579		0x14BA, 0x6000,
    580		PCI_ANY_ID, PCI_ANY_ID,
    581		0, 0,
    582		(kernel_ulong_t)&card_info_10mbit
    583	},
    584	{
    585		0x10B5, 0x2200,
    586		PCI_ANY_ID, PCI_ANY_ID,
    587		0, 0,
    588		(kernel_ulong_t)&card_info_10mbit
    589	},
    590	{ 0, }
    591};
    592
    593MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
    594
    595static struct pci_driver com20020pci_driver = {
    596	.name		= "com20020",
    597	.id_table	= com20020pci_id_table,
    598	.probe		= com20020pci_probe,
    599	.remove		= com20020pci_remove,
    600};
    601
    602static int __init com20020pci_init(void)
    603{
    604	if (BUGLVL(D_NORMAL))
    605		pr_info("%s\n", "COM20020 PCI support");
    606	return pci_register_driver(&com20020pci_driver);
    607}
    608
    609static void __exit com20020pci_cleanup(void)
    610{
    611	pci_unregister_driver(&com20020pci_driver);
    612}
    613
    614module_init(com20020pci_init)
    615module_exit(com20020pci_cleanup)