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

hydra.c (7681B)


      1/* New Hydra driver using generic 8390 core */
      2/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */
      3
      4/* This file is subject to the terms and conditions of the GNU General      */
      5/* Public License.  See the file COPYING in the main directory of the       */
      6/* Linux distribution for more details.                                     */
      7
      8/* Peter De Schrijver (p2@mind.be) */
      9/* Oldenburg 2000 */
     10
     11/* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a    */
     12/* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM  */
     13/* and 10BASE-2 (thin coax) and AUI connectors.                             */
     14
     15#include <linux/module.h>
     16#include <linux/kernel.h>
     17#include <linux/string.h>
     18#include <linux/errno.h>
     19#include <linux/ioport.h>
     20#include <linux/interrupt.h>
     21#include <linux/netdevice.h>
     22#include <linux/etherdevice.h>
     23#include <linux/skbuff.h>
     24#include <linux/init.h>
     25#include <linux/bitops.h>
     26
     27#include <asm/io.h>
     28#include <asm/irq.h>
     29#include <asm/amigaints.h>
     30#include <asm/amigahw.h>
     31#include <linux/zorro.h>
     32
     33#define EI_SHIFT(x)	(ei_local->reg_offset[x])
     34#define ei_inb(port)   in_8(port)
     35#define ei_outb(val,port)  out_8(port,val)
     36#define ei_inb_p(port)   in_8(port)
     37#define ei_outb_p(val,port)  out_8(port,val)
     38
     39static const char version[] =
     40    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
     41
     42#include "lib8390.c"
     43
     44#define NE_EN0_DCFG     (0x0e*2)
     45
     46#define NESM_START_PG   0x0    /* First page of TX buffer */
     47#define NESM_STOP_PG    0x40    /* Last page +1 of RX ring */
     48
     49#define HYDRA_NIC_BASE 0xffe1
     50#define HYDRA_ADDRPROM 0xffc0
     51#define HYDRA_VERSION "v3.0alpha"
     52
     53#define WORDSWAP(a)     ((((a)>>8)&0xff) | ((a)<<8))
     54
     55
     56static int hydra_init_one(struct zorro_dev *z,
     57				    const struct zorro_device_id *ent);
     58static int hydra_init(struct zorro_dev *z);
     59static int hydra_open(struct net_device *dev);
     60static int hydra_close(struct net_device *dev);
     61static void hydra_reset_8390(struct net_device *dev);
     62static void hydra_get_8390_hdr(struct net_device *dev,
     63			       struct e8390_pkt_hdr *hdr, int ring_page);
     64static void hydra_block_input(struct net_device *dev, int count,
     65			      struct sk_buff *skb, int ring_offset);
     66static void hydra_block_output(struct net_device *dev, int count,
     67			       const unsigned char *buf, int start_page);
     68static void hydra_remove_one(struct zorro_dev *z);
     69
     70static struct zorro_device_id hydra_zorro_tbl[] = {
     71    { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
     72    { 0 }
     73};
     74MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl);
     75
     76static struct zorro_driver hydra_driver = {
     77    .name	= "hydra",
     78    .id_table	= hydra_zorro_tbl,
     79    .probe	= hydra_init_one,
     80    .remove	= hydra_remove_one,
     81};
     82
     83static int hydra_init_one(struct zorro_dev *z,
     84			  const struct zorro_device_id *ent)
     85{
     86    int err;
     87
     88    if (!request_mem_region(z->resource.start, 0x10000, "Hydra"))
     89	return -EBUSY;
     90    if ((err = hydra_init(z))) {
     91	release_mem_region(z->resource.start, 0x10000);
     92	return -EBUSY;
     93    }
     94    return 0;
     95}
     96
     97static const struct net_device_ops hydra_netdev_ops = {
     98	.ndo_open		= hydra_open,
     99	.ndo_stop		= hydra_close,
    100
    101	.ndo_start_xmit		= __ei_start_xmit,
    102	.ndo_tx_timeout		= __ei_tx_timeout,
    103	.ndo_get_stats		= __ei_get_stats,
    104	.ndo_set_rx_mode	= __ei_set_multicast_list,
    105	.ndo_validate_addr	= eth_validate_addr,
    106	.ndo_set_mac_address	= eth_mac_addr,
    107#ifdef CONFIG_NET_POLL_CONTROLLER
    108	.ndo_poll_controller	= __ei_poll,
    109#endif
    110};
    111
    112static int hydra_init(struct zorro_dev *z)
    113{
    114    struct net_device *dev;
    115    unsigned long board = (unsigned long)ZTWO_VADDR(z->resource.start);
    116    unsigned long ioaddr = board+HYDRA_NIC_BASE;
    117    const char name[] = "NE2000";
    118    int start_page, stop_page;
    119    u8 macaddr[ETH_ALEN];
    120    int j;
    121    int err;
    122
    123    static u32 hydra_offsets[16] = {
    124	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
    125	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
    126    };
    127
    128    dev = ____alloc_ei_netdev(0);
    129    if (!dev)
    130	return -ENOMEM;
    131
    132    for (j = 0; j < ETH_ALEN; j++)
    133	macaddr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j));
    134    eth_hw_addr_set(dev, macaddr);
    135
    136    /* We must set the 8390 for word mode. */
    137    z_writeb(0x4b, ioaddr + NE_EN0_DCFG);
    138    start_page = NESM_START_PG;
    139    stop_page = NESM_STOP_PG;
    140
    141    dev->base_addr = ioaddr;
    142    dev->irq = IRQ_AMIGA_PORTS;
    143
    144    /* Install the Interrupt handler */
    145    if (request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, "Hydra Ethernet",
    146		    dev)) {
    147	free_netdev(dev);
    148	return -EAGAIN;
    149    }
    150
    151    ei_status.name = name;
    152    ei_status.tx_start_page = start_page;
    153    ei_status.stop_page = stop_page;
    154    ei_status.word16 = 1;
    155    ei_status.bigendian = 1;
    156
    157    ei_status.rx_start_page = start_page + TX_PAGES;
    158
    159    ei_status.reset_8390 = hydra_reset_8390;
    160    ei_status.block_input = hydra_block_input;
    161    ei_status.block_output = hydra_block_output;
    162    ei_status.get_8390_hdr = hydra_get_8390_hdr;
    163    ei_status.reg_offset = hydra_offsets;
    164
    165    dev->netdev_ops = &hydra_netdev_ops;
    166    __NS8390_init(dev, 0);
    167
    168    err = register_netdev(dev);
    169    if (err) {
    170	free_irq(IRQ_AMIGA_PORTS, dev);
    171	free_netdev(dev);
    172	return err;
    173    }
    174
    175    zorro_set_drvdata(z, dev);
    176
    177    pr_info("%s: Hydra at %pR, address %pM (hydra.c " HYDRA_VERSION ")\n",
    178	    dev->name, &z->resource, dev->dev_addr);
    179
    180    return 0;
    181}
    182
    183static int hydra_open(struct net_device *dev)
    184{
    185    __ei_open(dev);
    186    return 0;
    187}
    188
    189static int hydra_close(struct net_device *dev)
    190{
    191    struct ei_device *ei_local = netdev_priv(dev);
    192
    193    netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n");
    194    __ei_close(dev);
    195    return 0;
    196}
    197
    198static void hydra_reset_8390(struct net_device *dev)
    199{
    200    netdev_info(dev, "Hydra hw reset not there\n");
    201}
    202
    203static void hydra_get_8390_hdr(struct net_device *dev,
    204			       struct e8390_pkt_hdr *hdr, int ring_page)
    205{
    206    int nic_base = dev->base_addr;
    207    short *ptrs;
    208    unsigned long hdr_start= (nic_base-HYDRA_NIC_BASE) +
    209			     ((ring_page - NESM_START_PG)<<8);
    210    ptrs = (short *)hdr;
    211
    212    *(ptrs++) = z_readw(hdr_start);
    213    *((short *)hdr) = WORDSWAP(*((short *)hdr));
    214    hdr_start += 2;
    215    *(ptrs++) = z_readw(hdr_start);
    216    *((short *)hdr+1) = WORDSWAP(*((short *)hdr+1));
    217}
    218
    219static void hydra_block_input(struct net_device *dev, int count,
    220			      struct sk_buff *skb, int ring_offset)
    221{
    222    unsigned long nic_base = dev->base_addr;
    223    unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
    224    unsigned long xfer_start = mem_base + ring_offset - (NESM_START_PG<<8);
    225
    226    if (count&1)
    227	count++;
    228
    229    if (xfer_start+count >  mem_base + (NESM_STOP_PG<<8)) {
    230	int semi_count = (mem_base + (NESM_STOP_PG<<8)) - xfer_start;
    231
    232	z_memcpy_fromio(skb->data,xfer_start,semi_count);
    233	count -= semi_count;
    234	z_memcpy_fromio(skb->data+semi_count, mem_base, count);
    235    } else
    236	z_memcpy_fromio(skb->data, xfer_start,count);
    237
    238}
    239
    240static void hydra_block_output(struct net_device *dev, int count,
    241			       const unsigned char *buf, int start_page)
    242{
    243    unsigned long nic_base = dev->base_addr;
    244    unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
    245
    246    if (count&1)
    247	count++;
    248
    249    z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
    250}
    251
    252static void hydra_remove_one(struct zorro_dev *z)
    253{
    254    struct net_device *dev = zorro_get_drvdata(z);
    255
    256    unregister_netdev(dev);
    257    free_irq(IRQ_AMIGA_PORTS, dev);
    258    release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000);
    259    free_netdev(dev);
    260}
    261
    262static int __init hydra_init_module(void)
    263{
    264    return zorro_register_driver(&hydra_driver);
    265}
    266
    267static void __exit hydra_cleanup_module(void)
    268{
    269    zorro_unregister_driver(&hydra_driver);
    270}
    271
    272module_init(hydra_init_module);
    273module_exit(hydra_cleanup_module);
    274
    275MODULE_LICENSE("GPL");