brintos

brintos / linux-shallow public Read only

0
0
Text · 7.2 KiB · 6cc0e19 Raw
301 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.3 *4 * Copyright (C) 1999 kaz Kojima5 */6 7#include <linux/module.h>8#include <linux/kernel.h>9#include <linux/errno.h>10#include <linux/interrupt.h>11#include <linux/ioport.h>12#include <linux/netdevice.h>13#include <linux/etherdevice.h>14#include <linux/init.h>15#include <linux/delay.h>16 17#include <asm/io.h>18#include <mach-se/mach/se.h>19#include <asm/machvec.h>20#ifdef CONFIG_SH_STANDARD_BIOS21#include <asm/sh_bios.h>22#endif23 24#include "8390.h"25 26#define DRV_NAME "stnic"27 28#define byte	unsigned char29#define half	unsigned short30#define word	unsigned int31#define vbyte	volatile unsigned char32#define vhalf	volatile unsigned short33#define vword	volatile unsigned int34 35#define STNIC_RUN	0x01	/* 1 == Run, 0 == reset. */36 37#define START_PG	0	/* First page of TX buffer */38#define STOP_PG		128	/* Last page +1 of RX ring */39 40/* Alias */41#define STNIC_CR	E8390_CMD42#define PG0_RSAR0	EN0_RSARLO43#define PG0_RSAR1	EN0_RSARHI44#define PG0_RBCR0	EN0_RCNTLO45#define PG0_RBCR1	EN0_RCNTHI46 47#define CR_RRD		E8390_RREAD48#define CR_RWR		E8390_RWRITE49#define CR_PG0		E8390_PAGE050#define CR_STA		E8390_START51#define CR_RDMA		E8390_NODMA52 53/* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS.  */54static byte stnic_eadr[6] =55{0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07};56 57static struct net_device *stnic_dev;58 59static void stnic_reset (struct net_device *dev);60static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,61			   int ring_page);62static void stnic_block_input (struct net_device *dev, int count,63			       struct sk_buff *skb , int ring_offset);64static void stnic_block_output (struct net_device *dev, int count,65				const unsigned char *buf, int start_page);66 67static void stnic_init (struct net_device *dev);68 69static u32 stnic_msg_enable;70 71module_param_named(msg_enable, stnic_msg_enable, uint, 0444);72MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");73 74/* SH7750 specific read/write io. */75static inline void76STNIC_DELAY (void)77{78  vword trash;79  trash = *(vword *) 0xa0000000;80  trash = *(vword *) 0xa0000000;81  trash = *(vword *) 0xa0000000;82}83 84static inline byte85STNIC_READ (int reg)86{87  byte val;88 89  val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff;90  STNIC_DELAY ();91  return val;92}93 94static inline void95STNIC_WRITE (int reg, byte val)96{97  *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8);98  STNIC_DELAY ();99}100 101static int __init stnic_probe(void)102{103  struct net_device *dev;104  struct ei_device *ei_local;105  int err;106 107  /* If we are not running on a SolutionEngine, give up now */108  if (! MACH_SE)109    return -ENODEV;110 111  /* New style probing API */112  dev = alloc_ei_netdev();113  if (!dev)114	return -ENOMEM;115 116#ifdef CONFIG_SH_STANDARD_BIOS117  sh_bios_get_node_addr (stnic_eadr);118#endif119  eth_hw_addr_set(dev, stnic_eadr);120 121  /* Set the base address to point to the NIC, not the "real" base! */122  dev->base_addr = 0x1000;123  dev->irq = IRQ_STNIC;124  dev->netdev_ops = &ei_netdev_ops;125 126  /* Snarf the interrupt now.  There's no point in waiting since we cannot127     share and the board will usually be enabled. */128  err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);129  if (err)  {130	netdev_emerg(dev, " unable to get IRQ %d.\n", dev->irq);131	free_netdev(dev);132	return err;133  }134 135  ei_status.name = dev->name;136  ei_status.word16 = 1;137#ifdef __LITTLE_ENDIAN__138  ei_status.bigendian = 0;139#else140  ei_status.bigendian = 1;141#endif142  ei_status.tx_start_page = START_PG;143  ei_status.rx_start_page = START_PG + TX_PAGES;144  ei_status.stop_page = STOP_PG;145 146  ei_status.reset_8390 = &stnic_reset;147  ei_status.get_8390_hdr = &stnic_get_hdr;148  ei_status.block_input = &stnic_block_input;149  ei_status.block_output = &stnic_block_output;150 151  stnic_init (dev);152  ei_local = netdev_priv(dev);153  ei_local->msg_enable = stnic_msg_enable;154 155  err = register_netdev(dev);156  if (err) {157    free_irq(dev->irq, dev);158    free_netdev(dev);159    return err;160  }161  stnic_dev = dev;162 163  netdev_info(dev, "NS ST-NIC 83902A\n");164 165  return 0;166}167 168static void169stnic_reset (struct net_device *dev)170{171  struct ei_device *ei_local = netdev_priv(dev);172 173  *(vhalf *) PA_83902_RST = 0;174  udelay (5);175  netif_warn(ei_local, hw, dev, "8390 reset done (%ld).\n", jiffies);176  *(vhalf *) PA_83902_RST = ~0;177  udelay (5);178}179 180static void181stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,182	       int ring_page)183{184  struct ei_device *ei_local = netdev_priv(dev);185 186  half buf[2];187 188  STNIC_WRITE (PG0_RSAR0, 0);189  STNIC_WRITE (PG0_RSAR1, ring_page);190  STNIC_WRITE (PG0_RBCR0, 4);191  STNIC_WRITE (PG0_RBCR1, 0);192  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);193 194  buf[0] = *(vhalf *) PA_83902_IF;195  STNIC_DELAY ();196  buf[1] = *(vhalf *) PA_83902_IF;197  STNIC_DELAY ();198  hdr->next = buf[0] >> 8;199  hdr->status = buf[0] & 0xff;200#ifdef __LITTLE_ENDIAN__201  hdr->count = buf[1];202#else203  hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);204#endif205 206  netif_dbg(ei_local, probe, dev, "ring %x status %02x next %02x count %04x.\n",207	    ring_page, hdr->status, hdr->next, hdr->count);208 209  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);210}211 212/* Block input and output, similar to the Crynwr packet driver. If you are213   porting to a new ethercard look at the packet driver source for hints.214   The HP LAN doesn't use shared memory -- we put the packet215   out through the "remote DMA" dataport. */216 217static void218stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb,219		   int offset)220{221  char *buf = skb->data;222  half val;223 224  STNIC_WRITE (PG0_RSAR0, offset & 0xff);225  STNIC_WRITE (PG0_RSAR1, offset >> 8);226  STNIC_WRITE (PG0_RBCR0, length & 0xff);227  STNIC_WRITE (PG0_RBCR1, length >> 8);228  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);229 230  if (length & 1)231    length++;232 233  while (length > 0)234    {235      val = *(vhalf *) PA_83902_IF;236#ifdef __LITTLE_ENDIAN__237      *buf++ = val & 0xff;238      *buf++ = val >> 8;239#else240      *buf++ = val >> 8;241      *buf++ = val & 0xff;242#endif243      STNIC_DELAY ();244      length -= sizeof (half);245    }246 247  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);248}249 250static void251stnic_block_output (struct net_device *dev, int length,252		    const unsigned char *buf, int output_page)253{254  STNIC_WRITE (PG0_RBCR0, 1);	/* Write non-zero value */255  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);256  STNIC_DELAY ();257 258  STNIC_WRITE (PG0_RBCR0, length & 0xff);259  STNIC_WRITE (PG0_RBCR1, length >> 8);260  STNIC_WRITE (PG0_RSAR0, 0);261  STNIC_WRITE (PG0_RSAR1, output_page);262  STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA);263 264  if (length & 1)265    length++;266 267  while (length > 0)268    {269#ifdef __LITTLE_ENDIAN__270      *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0];271#else272      *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1];273#endif274      STNIC_DELAY ();275      buf += sizeof (half);276      length -= sizeof (half);277    }278 279  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);280}281 282/* This function resets the STNIC if something screws up.  */283static void284stnic_init (struct net_device *dev)285{286  stnic_reset (dev);287  NS8390_init (dev, 0);288}289 290static void __exit stnic_cleanup(void)291{292	unregister_netdev(stnic_dev);293	free_irq(stnic_dev->irq, stnic_dev);294	free_netdev(stnic_dev);295}296 297module_init(stnic_probe);298module_exit(stnic_cleanup);299MODULE_DESCRIPTION("National Semiconductor DP83902AV ethernet driver");300MODULE_LICENSE("GPL");301