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

com90io.c (11825B)


      1/*
      2 * Linux ARCnet driver - COM90xx chipset (IO-mapped buffers)
      3 *
      4 * Written 1997 by David Woodhouse.
      5 * Written 1994-1999 by Avery Pennarun.
      6 * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
      7 * Derived from skeleton.c by Donald Becker.
      8 *
      9 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
     10 *  for sponsoring the further development of this driver.
     11 *
     12 * **********************
     13 *
     14 * The original copyright of skeleton.c was as follows:
     15 *
     16 * skeleton.c Written 1993 by Donald Becker.
     17 * Copyright 1993 United States Government as represented by the
     18 * Director, National Security Agency.  This software may only be used
     19 * and distributed according to the terms of the GNU General Public License as
     20 * modified by SRC, incorporated herein by reference.
     21 *
     22 * **********************
     23 *
     24 * For more details, see drivers/net/arcnet.c
     25 *
     26 * **********************
     27 */
     28
     29#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
     30
     31#include <linux/kernel.h>
     32#include <linux/module.h>
     33#include <linux/moduleparam.h>
     34#include <linux/ioport.h>
     35#include <linux/delay.h>
     36#include <linux/netdevice.h>
     37#include <linux/memblock.h>
     38#include <linux/init.h>
     39#include <linux/interrupt.h>
     40#include <linux/io.h>
     41
     42#include "arcdevice.h"
     43#include "com9026.h"
     44
     45/* Internal function declarations */
     46
     47static int com90io_found(struct net_device *dev);
     48static void com90io_command(struct net_device *dev, int command);
     49static int com90io_status(struct net_device *dev);
     50static void com90io_setmask(struct net_device *dev, int mask);
     51static int com90io_reset(struct net_device *dev, int really_reset);
     52static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset,
     53				 void *buf, int count);
     54static void com90io_copy_from_card(struct net_device *dev, int bufnum,
     55				   int offset, void *buf, int count);
     56
     57/* Handy defines for ARCnet specific stuff */
     58
     59/* The number of low I/O ports used by the card. */
     60#define ARCNET_TOTAL_SIZE 16
     61
     62/****************************************************************************
     63 *                                                                          *
     64 * IO-mapped operation routines                                             *
     65 *                                                                          *
     66 ****************************************************************************/
     67
     68#undef ONE_AT_A_TIME_TX
     69#undef ONE_AT_A_TIME_RX
     70
     71static u_char get_buffer_byte(struct net_device *dev, unsigned offset)
     72{
     73	int ioaddr = dev->base_addr;
     74
     75	arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
     76	arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
     77
     78	return arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
     79}
     80
     81#ifdef ONE_AT_A_TIME_TX
     82static void put_buffer_byte(struct net_device *dev, unsigned offset,
     83			    u_char datum)
     84{
     85	int ioaddr = dev->base_addr;
     86
     87	arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
     88	arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
     89
     90	arcnet_outb(datum, ioaddr, COM9026_REG_RW_MEMDATA);
     91}
     92
     93#endif
     94
     95static void get_whole_buffer(struct net_device *dev, unsigned offset,
     96			     unsigned length, char *dest)
     97{
     98	int ioaddr = dev->base_addr;
     99
    100	arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
    101	arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
    102
    103	while (length--)
    104#ifdef ONE_AT_A_TIME_RX
    105		*(dest++) = get_buffer_byte(dev, offset++);
    106#else
    107		*(dest++) = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
    108#endif
    109}
    110
    111static void put_whole_buffer(struct net_device *dev, unsigned offset,
    112			     unsigned length, char *dest)
    113{
    114	int ioaddr = dev->base_addr;
    115
    116	arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
    117	arcnet_outb(offset & 0xff, ioaddr,COM9026_REG_W_ADDR_LO);
    118
    119	while (length--)
    120#ifdef ONE_AT_A_TIME_TX
    121		put_buffer_byte(dev, offset++, *(dest++));
    122#else
    123		arcnet_outb(*(dest++), ioaddr, COM9026_REG_RW_MEMDATA);
    124#endif
    125}
    126
    127/* We cannot probe for an IO mapped card either, although we can check that
    128 * it's where we were told it was, and even autoirq
    129 */
    130static int __init com90io_probe(struct net_device *dev)
    131{
    132	int ioaddr = dev->base_addr, status;
    133	unsigned long airqmask;
    134
    135	if (BUGLVL(D_NORMAL)) {
    136		pr_info("%s\n", "COM90xx IO-mapped mode support (by David Woodhouse et el.)");
    137		pr_info("E-mail me if you actually test this driver, please!\n");
    138	}
    139
    140	if (!ioaddr) {
    141		arc_printk(D_NORMAL, dev, "No autoprobe for IO mapped cards; you must specify the base address!\n");
    142		return -ENODEV;
    143	}
    144	if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
    145		arc_printk(D_INIT_REASONS, dev, "IO request_region %x-%x failed\n",
    146			   ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
    147		return -ENXIO;
    148	}
    149	if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) {
    150		arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n",
    151			   ioaddr);
    152		goto err_out;
    153	}
    154	arcnet_inb(ioaddr, COM9026_REG_R_RESET);
    155	mdelay(RESETtime);
    156
    157	status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
    158
    159	if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
    160		arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n",
    161			   status);
    162		goto err_out;
    163	}
    164	arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status);
    165
    166	arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
    167		    ioaddr, COM9026_REG_W_COMMAND);
    168
    169	arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n",
    170		   status);
    171
    172	status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
    173
    174	if (status & RESETflag) {
    175		arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n",
    176			   status);
    177		goto err_out;
    178	}
    179	arcnet_outb((0x16 | IOMAPflag) & ~ENABLE16flag,
    180		    ioaddr, COM9026_REG_RW_CONFIG);
    181
    182	/* Read first loc'n of memory */
    183
    184	arcnet_outb(AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
    185	arcnet_outb(0, ioaddr,  COM9026_REG_W_ADDR_LO);
    186
    187	status = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
    188	if (status != 0xd1) {
    189		arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n",
    190			   status);
    191		goto err_out;
    192	}
    193	if (!dev->irq) {
    194		/* if we do this, we're sure to get an IRQ since the
    195		 * card has just reset and the NORXflag is on until
    196		 * we tell it to start receiving.
    197		 */
    198
    199		airqmask = probe_irq_on();
    200		arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK);
    201		udelay(1);
    202		arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK);
    203		dev->irq = probe_irq_off(airqmask);
    204
    205		if ((int)dev->irq <= 0) {
    206			arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed\n");
    207			goto err_out;
    208		}
    209	}
    210	release_region(ioaddr, ARCNET_TOTAL_SIZE); /* end of probing */
    211	return com90io_found(dev);
    212
    213err_out:
    214	release_region(ioaddr, ARCNET_TOTAL_SIZE);
    215	return -ENODEV;
    216}
    217
    218/* Set up the struct net_device associated with this card.  Called after
    219 * probing succeeds.
    220 */
    221static int __init com90io_found(struct net_device *dev)
    222{
    223	struct arcnet_local *lp;
    224	int ioaddr = dev->base_addr;
    225	int err;
    226
    227	/* Reserve the irq */
    228	if (request_irq(dev->irq, arcnet_interrupt, 0,
    229			"arcnet (COM90xx-IO)", dev)) {
    230		arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
    231		return -ENODEV;
    232	}
    233	/* Reserve the I/O region */
    234	if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE,
    235			    "arcnet (COM90xx-IO)")) {
    236		free_irq(dev->irq, dev);
    237		return -EBUSY;
    238	}
    239
    240	lp = netdev_priv(dev);
    241	lp->card_name = "COM90xx I/O";
    242	lp->hw.command = com90io_command;
    243	lp->hw.status = com90io_status;
    244	lp->hw.intmask = com90io_setmask;
    245	lp->hw.reset = com90io_reset;
    246	lp->hw.owner = THIS_MODULE;
    247	lp->hw.copy_to_card = com90io_copy_to_card;
    248	lp->hw.copy_from_card = com90io_copy_from_card;
    249
    250	lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
    251	arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
    252
    253	/* get and check the station ID from offset 1 in shmem */
    254
    255	arcnet_set_addr(dev, get_buffer_byte(dev, 1));
    256
    257	err = register_netdev(dev);
    258	if (err) {
    259		arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag,
    260			    ioaddr, COM9026_REG_RW_CONFIG);
    261		free_irq(dev->irq, dev);
    262		release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
    263		return err;
    264	}
    265
    266	arc_printk(D_NORMAL, dev, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n",
    267		   dev->dev_addr[0], dev->base_addr, dev->irq);
    268
    269	return 0;
    270}
    271
    272/* Do a hardware reset on the card, and set up necessary registers.
    273 *
    274 * This should be called as little as possible, because it disrupts the
    275 * token on the network (causes a RECON) and requires a significant delay.
    276 *
    277 * However, it does make sure the card is in a defined state.
    278 */
    279static int com90io_reset(struct net_device *dev, int really_reset)
    280{
    281	struct arcnet_local *lp = netdev_priv(dev);
    282	short ioaddr = dev->base_addr;
    283
    284	arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
    285		   dev->name, arcnet_inb(ioaddr, COM9026_REG_R_STATUS));
    286
    287	if (really_reset) {
    288		/* reset the card */
    289		arcnet_inb(ioaddr, COM9026_REG_R_RESET);
    290		mdelay(RESETtime);
    291	}
    292	/* Set the thing to IO-mapped, 8-bit  mode */
    293	lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag;
    294	arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
    295
    296	arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
    297					/* clear flags & end reset */
    298	arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
    299
    300	/* verify that the ARCnet signature byte is present */
    301	if (get_buffer_byte(dev, 0) != TESTvalue) {
    302		arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
    303		return 1;
    304	}
    305	/* enable extended (512-byte) packets */
    306	arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
    307	/* done!  return success. */
    308	return 0;
    309}
    310
    311static void com90io_command(struct net_device *dev, int cmd)
    312{
    313	short ioaddr = dev->base_addr;
    314
    315	arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND);
    316}
    317
    318static int com90io_status(struct net_device *dev)
    319{
    320	short ioaddr = dev->base_addr;
    321
    322	return arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
    323}
    324
    325static void com90io_setmask(struct net_device *dev, int mask)
    326{
    327	short ioaddr = dev->base_addr;
    328
    329	arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK);
    330}
    331
    332static void com90io_copy_to_card(struct net_device *dev, int bufnum,
    333				 int offset, void *buf, int count)
    334{
    335	TIME(dev, "put_whole_buffer", count,
    336	     put_whole_buffer(dev, bufnum * 512 + offset, count, buf));
    337}
    338
    339static void com90io_copy_from_card(struct net_device *dev, int bufnum,
    340				   int offset, void *buf, int count)
    341{
    342	TIME(dev, "get_whole_buffer", count,
    343	     get_whole_buffer(dev, bufnum * 512 + offset, count, buf));
    344}
    345
    346static int io;			/* use the insmod io= irq= shmem= options */
    347static int irq;
    348static char device[9];		/* use eg. device=arc1 to change name */
    349
    350module_param_hw(io, int, ioport, 0);
    351module_param_hw(irq, int, irq, 0);
    352module_param_string(device, device, sizeof(device), 0);
    353MODULE_LICENSE("GPL");
    354
    355#ifndef MODULE
    356static int __init com90io_setup(char *s)
    357{
    358	int ints[4];
    359
    360	s = get_options(s, 4, ints);
    361	if (!ints[0])
    362		return 0;
    363	switch (ints[0]) {
    364	default:		/* ERROR */
    365		pr_err("Too many arguments\n");
    366		fallthrough;
    367	case 2:		/* IRQ */
    368		irq = ints[2];
    369		fallthrough;
    370	case 1:		/* IO address */
    371		io = ints[1];
    372	}
    373	if (*s)
    374		snprintf(device, sizeof(device), "%s", s);
    375	return 1;
    376}
    377__setup("com90io=", com90io_setup);
    378#endif
    379
    380static struct net_device *my_dev;
    381
    382static int __init com90io_init(void)
    383{
    384	struct net_device *dev;
    385	int err;
    386
    387	dev = alloc_arcdev(device);
    388	if (!dev)
    389		return -ENOMEM;
    390
    391	dev->base_addr = io;
    392	dev->irq = irq;
    393	if (dev->irq == 2)
    394		dev->irq = 9;
    395
    396	err = com90io_probe(dev);
    397
    398	if (err) {
    399		free_arcdev(dev);
    400		return err;
    401	}
    402
    403	my_dev = dev;
    404	return 0;
    405}
    406
    407static void __exit com90io_exit(void)
    408{
    409	struct net_device *dev = my_dev;
    410	int ioaddr = dev->base_addr;
    411
    412	unregister_netdev(dev);
    413
    414	/* In case the old driver is loaded later,
    415	 * set the thing back to MMAP mode
    416	 */
    417	arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag,
    418		    ioaddr, COM9026_REG_RW_CONFIG);
    419
    420	free_irq(dev->irq, dev);
    421	release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
    422	free_arcdev(dev);
    423}
    424
    425module_init(com90io_init)
    426module_exit(com90io_exit)