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