Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 079da354db3473b56eb938ca53a2cb0804ea9c8c 381 lines 8.9 kB view raw
1/* 2 * sonic.c 3 * 4 * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) 5 * 6 * This driver is based on work from Andreas Busse, but most of 7 * the code is rewritten. 8 * 9 * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) 10 * 11 * A driver for the onboard Sonic ethernet controller on Mips Jazz 12 * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and 13 * perhaps others, too) 14 */ 15 16#include <linux/kernel.h> 17#include <linux/module.h> 18#include <linux/types.h> 19#include <linux/fcntl.h> 20#include <linux/interrupt.h> 21#include <linux/init.h> 22#include <linux/ioport.h> 23#include <linux/in.h> 24#include <linux/slab.h> 25#include <linux/string.h> 26#include <linux/delay.h> 27#include <linux/errno.h> 28#include <linux/netdevice.h> 29#include <linux/etherdevice.h> 30#include <linux/skbuff.h> 31#include <linux/bitops.h> 32#include <linux/device.h> 33 34#include <asm/bootinfo.h> 35#include <asm/system.h> 36#include <asm/pgtable.h> 37#include <asm/io.h> 38#include <asm/dma.h> 39#include <asm/jazz.h> 40#include <asm/jazzdma.h> 41 42static char jazz_sonic_string[] = "jazzsonic"; 43static struct platform_device *jazz_sonic_device; 44 45#define SONIC_MEM_SIZE 0x100 46 47#define SREGS_PAD(n) u16 n; 48 49#include "sonic.h" 50 51/* 52 * Macros to access SONIC registers 53 */ 54#define SONIC_READ(reg) (*((volatile unsigned int *)base_addr+reg)) 55 56#define SONIC_WRITE(reg,val) \ 57do { \ 58 *((volatile unsigned int *)base_addr+(reg)) = (val); \ 59} while (0) 60 61 62/* use 0 for production, 1 for verification, >2 for debug */ 63#ifdef SONIC_DEBUG 64static unsigned int sonic_debug = SONIC_DEBUG; 65#else 66static unsigned int sonic_debug = 1; 67#endif 68 69/* 70 * Base address and interrupt of the SONIC controller on JAZZ boards 71 */ 72static struct { 73 unsigned int port; 74 unsigned int irq; 75} sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}}; 76 77/* 78 * We cannot use station (ethernet) address prefixes to detect the 79 * sonic controller since these are board manufacturer depended. 80 * So we check for known Silicon Revision IDs instead. 81 */ 82static unsigned short known_revisions[] = 83{ 84 0x04, /* Mips Magnum 4000 */ 85 0xffff /* end of list */ 86}; 87 88static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr, 89 unsigned int irq) 90{ 91 static unsigned version_printed; 92 unsigned int silicon_revision; 93 unsigned int val; 94 struct sonic_local *lp; 95 int err = -ENODEV; 96 int i; 97 98 if (!request_mem_region(base_addr, SONIC_MEM_SIZE, jazz_sonic_string)) 99 return -EBUSY; 100 /* 101 * get the Silicon Revision ID. If this is one of the known 102 * one assume that we found a SONIC ethernet controller at 103 * the expected location. 104 */ 105 silicon_revision = SONIC_READ(SONIC_SR); 106 if (sonic_debug > 1) 107 printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); 108 109 i = 0; 110 while (known_revisions[i] != 0xffff 111 && known_revisions[i] != silicon_revision) 112 i++; 113 114 if (known_revisions[i] == 0xffff) { 115 printk("SONIC ethernet controller not found (0x%4x)\n", 116 silicon_revision); 117 goto out; 118 } 119 120 if (sonic_debug && version_printed++ == 0) 121 printk(version); 122 123 printk("%s: Sonic ethernet found at 0x%08lx, ", dev->name, base_addr); 124 125 /* Fill in the 'dev' fields. */ 126 dev->base_addr = base_addr; 127 dev->irq = irq; 128 129 /* 130 * Put the sonic into software reset, then 131 * retrieve and print the ethernet address. 132 */ 133 SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); 134 SONIC_WRITE(SONIC_CEP,0); 135 for (i=0; i<3; i++) { 136 val = SONIC_READ(SONIC_CAP0-i); 137 dev->dev_addr[i*2] = val; 138 dev->dev_addr[i*2+1] = val >> 8; 139 } 140 141 printk("HW Address "); 142 for (i = 0; i < 6; i++) { 143 printk("%2.2x", dev->dev_addr[i]); 144 if (i<5) 145 printk(":"); 146 } 147 148 printk(" IRQ %d\n", irq); 149 150 err = -ENOMEM; 151 152 /* Initialize the device structure. */ 153 if (dev->priv == NULL) { 154 /* 155 * the memory be located in the same 64kb segment 156 */ 157 lp = NULL; 158 i = 0; 159 do { 160 lp = kmalloc(sizeof(*lp), GFP_KERNEL); 161 if ((unsigned long) lp >> 16 162 != ((unsigned long)lp + sizeof(*lp) ) >> 16) { 163 /* FIXME, free the memory later */ 164 kfree(lp); 165 lp = NULL; 166 } 167 } while (lp == NULL && i++ < 20); 168 169 if (lp == NULL) { 170 printk("%s: couldn't allocate memory for descriptors\n", 171 dev->name); 172 goto out; 173 } 174 175 memset(lp, 0, sizeof(struct sonic_local)); 176 177 /* get the virtual dma address */ 178 lp->cda_laddr = vdma_alloc(CPHYSADDR(lp),sizeof(*lp)); 179 if (lp->cda_laddr == ~0UL) { 180 printk("%s: couldn't get DMA page entry for " 181 "descriptors\n", dev->name); 182 goto out1; 183 } 184 185 lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda); 186 lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda); 187 lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra); 188 189 /* allocate receive buffer area */ 190 /* FIXME, maybe we should use skbs */ 191 lp->rba = kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL); 192 if (!lp->rba) { 193 printk("%s: couldn't allocate receive buffers\n", 194 dev->name); 195 goto out2; 196 } 197 198 /* get virtual dma address */ 199 lp->rba_laddr = vdma_alloc(CPHYSADDR(lp->rba), 200 SONIC_NUM_RRS * SONIC_RBSIZE); 201 if (lp->rba_laddr == ~0UL) { 202 printk("%s: couldn't get DMA page entry for receive " 203 "buffers\n",dev->name); 204 goto out3; 205 } 206 207 /* now convert pointer to KSEG1 pointer */ 208 lp->rba = (char *)KSEG1ADDR(lp->rba); 209 flush_cache_all(); 210 dev->priv = (struct sonic_local *)KSEG1ADDR(lp); 211 } 212 213 lp = (struct sonic_local *)dev->priv; 214 dev->open = sonic_open; 215 dev->stop = sonic_close; 216 dev->hard_start_xmit = sonic_send_packet; 217 dev->get_stats = sonic_get_stats; 218 dev->set_multicast_list = &sonic_multicast_list; 219 dev->watchdog_timeo = TX_TIMEOUT; 220 221 /* 222 * clear tally counter 223 */ 224 SONIC_WRITE(SONIC_CRCT,0xffff); 225 SONIC_WRITE(SONIC_FAET,0xffff); 226 SONIC_WRITE(SONIC_MPT,0xffff); 227 228 return 0; 229out3: 230 kfree(lp->rba); 231out2: 232 vdma_free(lp->cda_laddr); 233out1: 234 kfree(lp); 235out: 236 release_region(base_addr, SONIC_MEM_SIZE); 237 return err; 238} 239 240/* 241 * Probe for a SONIC ethernet controller on a Mips Jazz board. 242 * Actually probing is superfluous but we're paranoid. 243 */ 244static int __init jazz_sonic_probe(struct device *device) 245{ 246 struct net_device *dev; 247 struct sonic_local *lp; 248 unsigned long base_addr; 249 int err = 0; 250 int i; 251 252 /* 253 * Don't probe if we're not running on a Jazz board. 254 */ 255 if (mips_machgroup != MACH_GROUP_JAZZ) 256 return -ENODEV; 257 258 dev = alloc_etherdev(0); 259 if (!dev) 260 return -ENOMEM; 261 262 netdev_boot_setup_check(dev); 263 base_addr = dev->base_addr; 264 265 if (base_addr >= KSEG0) { /* Check a single specified location. */ 266 err = sonic_probe1(dev, base_addr, dev->irq); 267 } else if (base_addr != 0) { /* Don't probe at all. */ 268 err = -ENXIO; 269 } else { 270 for (i = 0; sonic_portlist[i].port; i++) { 271 int io = sonic_portlist[i].port; 272 if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0) 273 break; 274 } 275 if (!sonic_portlist[i].port) 276 err = -ENODEV; 277 } 278 if (err) 279 goto out; 280 err = register_netdev(dev); 281 if (err) 282 goto out1; 283 284 return 0; 285 286out1: 287 lp = dev->priv; 288 vdma_free(lp->rba_laddr); 289 kfree(lp->rba); 290 vdma_free(lp->cda_laddr); 291 kfree(lp); 292 release_region(dev->base_addr, SONIC_MEM_SIZE); 293out: 294 free_netdev(dev); 295 296 return err; 297} 298 299/* 300 * SONIC uses a normal IRQ 301 */ 302#define sonic_request_irq request_irq 303#define sonic_free_irq free_irq 304 305#define sonic_chiptomem(x) KSEG1ADDR(vdma_log2phys(x)) 306 307#include "sonic.c" 308 309static int __devexit jazz_sonic_device_remove (struct device *device) 310{ 311 struct net_device *dev = device->driver_data; 312 313 unregister_netdev (dev); 314 release_region (dev->base_addr, SONIC_MEM_SIZE); 315 free_netdev (dev); 316 317 return 0; 318} 319 320static struct device_driver jazz_sonic_driver = { 321 .name = jazz_sonic_string, 322 .bus = &platform_bus_type, 323 .probe = jazz_sonic_probe, 324 .remove = __devexit_p(jazz_sonic_device_remove), 325}; 326 327static void jazz_sonic_platform_release (struct device *device) 328{ 329 struct platform_device *pldev; 330 331 /* free device */ 332 pldev = to_platform_device (device); 333 kfree (pldev); 334} 335 336static int __init jazz_sonic_init_module(void) 337{ 338 struct platform_device *pldev; 339 340 if (driver_register(&jazz_sonic_driver)) { 341 printk(KERN_ERR "Driver registration failed\n"); 342 return -ENOMEM; 343 } 344 345 jazz_sonic_device = NULL; 346 347 if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) { 348 goto out_unregister; 349 } 350 351 memset(pldev, 0, sizeof (*pldev)); 352 pldev->name = jazz_sonic_string; 353 pldev->id = 0; 354 pldev->dev.release = jazz_sonic_platform_release; 355 jazz_sonic_device = pldev; 356 357 if (platform_device_register (pldev)) { 358 kfree(pldev); 359 jazz_sonic_device = NULL; 360 } 361 362 return 0; 363 364out_unregister: 365 platform_device_unregister(pldev); 366 367 return -ENOMEM; 368} 369 370static void __exit jazz_sonic_cleanup_module(void) 371{ 372 driver_unregister(&jazz_sonic_driver); 373 374 if (jazz_sonic_device) { 375 platform_device_unregister(jazz_sonic_device); 376 jazz_sonic_device = NULL; 377 } 378} 379 380module_init(jazz_sonic_init_module); 381module_exit(jazz_sonic_cleanup_module);