macsonic.c 17.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 * macsonic.c
 *
4 5 6 7 8 9
 * (C) 2005 Finn Thain
 *
 * Converted to DMA API, converted to unified driver model, made it work as
 * a module again, and from the mac68k project, introduced more 32-bit cards
 * and dhd's support for 16-bit cards.
 *
L
Linus Torvalds 已提交
10 11 12 13 14 15
 * (C) 1998 Alan Cox
 *
 * Debugging Andreas Ehliar, Michael Schmitz
 *
 * Based on code
 * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de)
16
 *
L
Linus Torvalds 已提交
17 18
 * This driver is based on work from Andreas Busse, but most of
 * the code is rewritten.
19
 *
L
Linus Torvalds 已提交
20 21 22 23
 * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
 *
 * A driver for the Mac onboard Sonic ethernet chip.
 *
24
 * 98/12/21 MSch: judged from tests on Q800, it's basically working,
L
Linus Torvalds 已提交
25 26 27 28
 *		  but eating up both receive and transmit resources
 *		  and duplicating packets. Needs more testing.
 *
 * 99/01/03 MSch: upgraded to version 0.92 of the core driver, fixed.
29
 *
L
Linus Torvalds 已提交
30 31 32 33 34
 * 00/10/31 sammy@oh.verio.com: Updated driver for 2.4 kernels, fixed problems
 *          on centris.
 */

#include <linux/kernel.h>
35
#include <linux/module.h>
L
Linus Torvalds 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/nubus.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
50
#include <linux/platform_device.h>
51
#include <linux/dma-mapping.h>
L
Linus Torvalds 已提交
52 53 54 55 56 57 58 59 60 61 62

#include <asm/bootinfo.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/hwtest.h>
#include <asm/dma.h>
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_via.h>

63 64
static char mac_sonic_string[] = "macsonic";
static struct platform_device *mac_sonic_device;
L
Linus Torvalds 已提交
65 66 67

#include "sonic.h"

68 69 70 71 72 73 74 75 76 77 78
/* These should basically be bus-size and endian independent (since
   the SONIC is at least smart enough that it uses the same endianness
   as the host, unlike certain less enlightened Macintosh NICs) */
#define SONIC_READ(reg) (nubus_readw(dev->base_addr + (reg * 4) \
	      + lp->reg_offset))
#define SONIC_WRITE(reg,val) (nubus_writew(val, dev->base_addr + (reg * 4) \
	      + lp->reg_offset))

/* use 0 for production, 1 for verification, >1 for debug */
#ifdef SONIC_DEBUG
static unsigned int sonic_debug = SONIC_DEBUG;
79
#else
80 81
static unsigned int sonic_debug = 1;
#endif
L
Linus Torvalds 已提交
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

static int sonic_version_printed;

extern int mac_onboard_sonic_probe(struct net_device* dev);
extern int mac_nubus_sonic_probe(struct net_device* dev);

/* For onboard SONIC */
#define ONBOARD_SONIC_REGISTERS	0x50F0A000
#define ONBOARD_SONIC_PROM_BASE	0x50f08000

enum macsonic_type {
	MACSONIC_DUODOCK,
	MACSONIC_APPLE,
	MACSONIC_APPLE16,
	MACSONIC_DAYNA,
	MACSONIC_DAYNALINK
};

/* For the built-in SONIC in the Duo Dock */
#define DUODOCK_SONIC_REGISTERS 0xe10000
#define DUODOCK_SONIC_PROM_BASE 0xe12000

/* For Apple-style NuBus SONIC */
#define APPLE_SONIC_REGISTERS	0
#define APPLE_SONIC_PROM_BASE	0x40000

/* Daynalink LC SONIC */
#define DAYNALINK_PROM_BASE 0x400000

/* For Dayna-style NuBus SONIC (haven't seen one yet) */
#define DAYNA_SONIC_REGISTERS   0x180000
/* This is what OpenBSD says.  However, this is definitely in NuBus
   ROM space so we should be able to get it by walking the NuBus
   resource directories */
#define DAYNA_SONIC_MAC_ADDR	0xffe004

#define SONIC_READ_PROM(addr) nubus_readb(prom_addr+addr)

/*
 * For reversing the PROM address
 */

static inline void bit_reverse_addr(unsigned char addr[6])
{
	int i;

	for(i = 0; i < 6; i++)
A
Akinobu Mita 已提交
129
		addr[i] = bitrev8(addr[i]);
L
Linus Torvalds 已提交
130 131 132 133
}

int __init macsonic_init(struct net_device* dev)
{
134
	struct sonic_local* lp = netdev_priv(dev);
L
Linus Torvalds 已提交
135 136 137

	/* Allocate the entire chunk of memory for the descriptors.
           Note that this cannot cross a 64K boundary. */
138 139 140 141
	if ((lp->descriptors = dma_alloc_coherent(lp->device,
	            SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
	            &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
		printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
L
Linus Torvalds 已提交
142
		return -ENOMEM;
143
	}
L
Linus Torvalds 已提交
144 145

	/* Now set up the pointers to point to the appropriate places */
146 147 148
	lp->cda = lp->descriptors;
	lp->tda = lp->cda + (SIZEOF_SONIC_CDA
	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
L
Linus Torvalds 已提交
149
	lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
150
	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
L
Linus Torvalds 已提交
151
	lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
152
	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
L
Linus Torvalds 已提交
153

154 155 156 157 158 159 160
	lp->cda_laddr = lp->descriptors_laddr;
	lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
	lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
	lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
	                     * SONIC_BUS_SCALE(lp->dma_bitmode));
L
Linus Torvalds 已提交
161 162 163 164 165 166

	dev->open = sonic_open;
	dev->stop = sonic_close;
	dev->hard_start_xmit = sonic_send_packet;
	dev->get_stats = sonic_get_stats;
	dev->set_multicast_list = &sonic_multicast_list;
167 168
	dev->tx_timeout = sonic_tx_timeout;
	dev->watchdog_timeo = TX_TIMEOUT;
L
Linus Torvalds 已提交
169 170 171 172

	/*
	 * clear tally counter
	 */
173 174 175
	SONIC_WRITE(SONIC_CRCT, 0xffff);
	SONIC_WRITE(SONIC_FAET, 0xffff);
	SONIC_WRITE(SONIC_MPT, 0xffff);
L
Linus Torvalds 已提交
176 177 178 179 180 181

	return 0;
}

int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
{
182
	struct sonic_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
183 184 185 186 187 188 189 190 191 192 193 194 195
	const int prom_addr = ONBOARD_SONIC_PROM_BASE;
	int i;

	/* On NuBus boards we can sometimes look in the ROM resources.
	   No such luck for comm-slot/onboard. */
	for(i = 0; i < 6; i++)
		dev->dev_addr[i] = SONIC_READ_PROM(i);

	/* Most of the time, the address is bit-reversed.  The NetBSD
	   source has a rather long and detailed historical account of
	   why this is so. */
	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
196
	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
L
Linus Torvalds 已提交
197 198 199 200 201 202 203 204 205 206 207
	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
		bit_reverse_addr(dev->dev_addr);
	else
		return 0;

	/* If we still have what seems to be a bogus address, we'll
           look in the CAM.  The top entry should be ours. */
	/* Danger! This only works if MacOS has already initialized
           the card... */
	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
208
	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
L
Linus Torvalds 已提交
209 210 211 212 213
	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
	{
		unsigned short val;

		printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n");
214

215 216
		SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
		SONIC_WRITE(SONIC_CEP, 15);
L
Linus Torvalds 已提交
217

218
		val = SONIC_READ(SONIC_CAP2);
L
Linus Torvalds 已提交
219 220
		dev->dev_addr[5] = val >> 8;
		dev->dev_addr[4] = val & 0xff;
221
		val = SONIC_READ(SONIC_CAP1);
L
Linus Torvalds 已提交
222 223
		dev->dev_addr[3] = val >> 8;
		dev->dev_addr[2] = val & 0xff;
224
		val = SONIC_READ(SONIC_CAP0);
L
Linus Torvalds 已提交
225 226
		dev->dev_addr[1] = val >> 8;
		dev->dev_addr[0] = val & 0xff;
227

L
Linus Torvalds 已提交
228 229 230 231 232 233 234 235 236 237 238
		printk(KERN_INFO "HW Address from CAM 15: ");
		for (i = 0; i < 6; i++) {
			printk("%2.2x", dev->dev_addr[i]);
			if (i < 5)
				printk(":");
		}
		printk("\n");
	} else return 0;

	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
239
	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
L
Linus Torvalds 已提交
240 241 242 243 244 245 246 247 248 249 250 251 252 253
	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
	{
		/*
		 * Still nonsense ... messed up someplace!
		 */
		printk(KERN_ERR "macsonic: ERROR (INVALID MAC)\n");
		return -EIO;
	} else return 0;
}

int __init mac_onboard_sonic_probe(struct net_device* dev)
{
	/* Bwahahaha */
	static int once_is_more_than_enough;
254 255 256
	struct sonic_local* lp = netdev_priv(dev);
	int sr;
	int commslot = 0;
257

L
Linus Torvalds 已提交
258 259 260 261 262 263 264 265 266
	if (once_is_more_than_enough)
		return -ENODEV;
	once_is_more_than_enough = 1;

	if (!MACH_IS_MAC)
		return -ENODEV;

	if (macintosh_config->ether_type != MAC_ETHER_SONIC)
		return -ENODEV;
267

268
	printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
269

L
Linus Torvalds 已提交
270 271 272 273 274 275
	/* Bogus probing, on the models which may or may not have
	   Ethernet (BTW, the Ethernet *is* always at the same
	   address, and nothing else lives there, at least if Apple's
	   documentation is to be believed) */
	if (macintosh_config->ident == MAC_MODEL_Q630 ||
	    macintosh_config->ident == MAC_MODEL_P588 ||
276
	    macintosh_config->ident == MAC_MODEL_P575 ||
L
Linus Torvalds 已提交
277 278 279 280 281 282 283 284 285 286 287 288
	    macintosh_config->ident == MAC_MODEL_C610) {
		unsigned long flags;
		int card_present;

		local_irq_save(flags);
		card_present = hwreg_present((void*)ONBOARD_SONIC_REGISTERS);
		local_irq_restore(flags);

		if (!card_present) {
			printk("none.\n");
			return -ENODEV;
		}
289
		commslot = 1;
L
Linus Torvalds 已提交
290 291
	}

292
	printk("yes\n");
L
Linus Torvalds 已提交
293

294 295
	/* Danger!  My arms are flailing wildly!  You *must* set lp->reg_offset
	 * and dev->base_addr before using SONIC_READ() or SONIC_WRITE() */
L
Linus Torvalds 已提交
296 297 298 299 300 301 302 303 304 305 306
	dev->base_addr = ONBOARD_SONIC_REGISTERS;
	if (via_alt_mapping)
		dev->irq = IRQ_AUTO_3;
	else
		dev->irq = IRQ_NUBUS_9;

	if (!sonic_version_printed) {
		printk(KERN_INFO "%s", version);
		sonic_version_printed = 1;
	}
	printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n",
307
	       lp->device->bus_id, dev->base_addr);
L
Linus Torvalds 已提交
308 309 310

	/* The PowerBook's SONIC is 16 bit always. */
	if (macintosh_config->ident == MAC_MODEL_PB520) {
311 312 313 314
		lp->reg_offset = 0;
		lp->dma_bitmode = SONIC_BITMODE16;
		sr = SONIC_READ(SONIC_SR);
	} else if (commslot) {
L
Linus Torvalds 已提交
315
		/* Some of the comm-slot cards are 16 bit.  But some
316 317 318 319 320 321 322 323
		   of them are not.  The 32-bit cards use offset 2 and
		   have known revisions, we try reading the revision
		   register at offset 2, if we don't get a known revision
		   we assume 16 bit at offset 0.  */
		lp->reg_offset = 2;
		lp->dma_bitmode = SONIC_BITMODE16;

		sr = SONIC_READ(SONIC_SR);
324
		if (sr == 0x0004 || sr == 0x0006 || sr == 0x0100 || sr == 0x0101)
325 326 327 328 329 330
			/* 83932 is 0x0004 or 0x0006, 83934 is 0x0100 or 0x0101 */
			lp->dma_bitmode = SONIC_BITMODE32;
		else {
			lp->dma_bitmode = SONIC_BITMODE16;
			lp->reg_offset = 0;
			sr = SONIC_READ(SONIC_SR);
L
Linus Torvalds 已提交
331
		}
332 333 334 335 336
	} else {
		/* All onboard cards are at offset 2 with 32 bit DMA. */
		lp->reg_offset = 2;
		lp->dma_bitmode = SONIC_BITMODE32;
		sr = SONIC_READ(SONIC_SR);
L
Linus Torvalds 已提交
337
	}
338 339 340
	printk(KERN_INFO
	       "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
	       lp->device->bus_id, sr, lp->dma_bitmode?32:16, lp->reg_offset);
L
Linus Torvalds 已提交
341

342 343 344 345
#if 0 /* This is sometimes useful to find out how MacOS configured the card. */
	printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
	       SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
#endif
L
Linus Torvalds 已提交
346 347

	/* Software reset, then initialize control registers. */
348 349 350 351 352
	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);

	SONIC_WRITE(SONIC_DCR, SONIC_DCR_EXBUS | SONIC_DCR_BMS |
	                       SONIC_DCR_RFT1  | SONIC_DCR_TFT0 |
	                       (lp->dma_bitmode ? SONIC_DCR_DW : 0));
L
Linus Torvalds 已提交
353 354

	/* This *must* be written back to in order to restore the
355 356 357
	 * extended programmable output bits, as it may not have been
	 * initialised since the hardware reset. */
	SONIC_WRITE(SONIC_DCR2, 0);
L
Linus Torvalds 已提交
358 359

	/* Clear *and* disable interrupts to be on the safe side */
360 361
	SONIC_WRITE(SONIC_IMR, 0);
	SONIC_WRITE(SONIC_ISR, 0x7fff);
L
Linus Torvalds 已提交
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377

	/* Now look for the MAC address. */
	if (mac_onboard_sonic_ethernet_addr(dev) != 0)
		return -ENODEV;

	/* Shared init code */
	return macsonic_init(dev);
}

int __init mac_nubus_sonic_ethernet_addr(struct net_device* dev,
					 unsigned long prom_addr,
					 int id)
{
	int i;
	for(i = 0; i < 6; i++)
		dev->dev_addr[i] = SONIC_READ_PROM(i);
378 379 380 381

	/* Some of the addresses are bit-reversed */
	if (id != MACSONIC_DAYNA)
		bit_reverse_addr(dev->dev_addr);
L
Linus Torvalds 已提交
382 383 384 385 386 387

	return 0;
}

int __init macsonic_ident(struct nubus_dev* ndev)
{
388
	if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
L
Linus Torvalds 已提交
389 390 391 392 393 394 395 396 397 398
	    ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
		return MACSONIC_DAYNALINK;
	if (ndev->dr_hw == NUBUS_DRHW_SONIC &&
	    ndev->dr_sw == NUBUS_DRSW_APPLE) {
		/* There has to be a better way to do this... */
		if (strstr(ndev->board->name, "DuoDock"))
			return MACSONIC_DUODOCK;
		else
			return MACSONIC_APPLE;
	}
399

400 401 402
	if (ndev->dr_hw == NUBUS_DRHW_SMC9194 &&
	    ndev->dr_sw == NUBUS_DRSW_DAYNA)
		return MACSONIC_DAYNA;
403

404 405 406 407
	if (ndev->dr_hw == NUBUS_DRHW_SONIC_LC &&
	    ndev->dr_sw == 0) { /* huh? */
		return MACSONIC_APPLE16;
	}
L
Linus Torvalds 已提交
408 409 410 411 412 413 414
	return -1;
}

int __init mac_nubus_sonic_probe(struct net_device* dev)
{
	static int slots;
	struct nubus_dev* ndev = NULL;
415
	struct sonic_local* lp = netdev_priv(dev);
L
Linus Torvalds 已提交
416 417
	unsigned long base_addr, prom_addr;
	u16 sonic_dcr;
418 419
	int id = -1;
	int reg_offset, dma_bitmode;
420

L
Linus Torvalds 已提交
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
	/* Find the first SONIC that hasn't been initialized already */
	while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
				       NUBUS_TYPE_ETHERNET, ndev)) != NULL)
	{
		/* Have we seen it already? */
		if (slots & (1<<ndev->board->slot))
			continue;
		slots |= 1<<ndev->board->slot;

		/* Is it one of ours? */
		if ((id = macsonic_ident(ndev)) != -1)
			break;
	}

	if (ndev == NULL)
		return -ENODEV;

	switch (id) {
	case MACSONIC_DUODOCK:
		base_addr = ndev->board->slot_addr + DUODOCK_SONIC_REGISTERS;
		prom_addr = ndev->board->slot_addr + DUODOCK_SONIC_PROM_BASE;
442 443
		sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1 |
		            SONIC_DCR_TFT0;
L
Linus Torvalds 已提交
444
		reg_offset = 2;
445
		dma_bitmode = SONIC_BITMODE32;
L
Linus Torvalds 已提交
446 447 448 449 450 451
		break;
	case MACSONIC_APPLE:
		base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
		prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
		sonic_dcr = SONIC_DCR_BMS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0;
		reg_offset = 0;
452
		dma_bitmode = SONIC_BITMODE32;
L
Linus Torvalds 已提交
453 454 455 456
		break;
	case MACSONIC_APPLE16:
		base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
		prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
457
		sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
458
		            SONIC_DCR_PO1 | SONIC_DCR_BMS;
L
Linus Torvalds 已提交
459
		reg_offset = 0;
460
		dma_bitmode = SONIC_BITMODE16;
L
Linus Torvalds 已提交
461 462 463 464
		break;
	case MACSONIC_DAYNALINK:
		base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
		prom_addr = ndev->board->slot_addr + DAYNALINK_PROM_BASE;
465
		sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
466
		            SONIC_DCR_PO1 | SONIC_DCR_BMS;
L
Linus Torvalds 已提交
467
		reg_offset = 0;
468
		dma_bitmode = SONIC_BITMODE16;
L
Linus Torvalds 已提交
469 470 471 472
		break;
	case MACSONIC_DAYNA:
		base_addr = ndev->board->slot_addr + DAYNA_SONIC_REGISTERS;
		prom_addr = ndev->board->slot_addr + DAYNA_SONIC_MAC_ADDR;
473 474
		sonic_dcr = SONIC_DCR_BMS |
		            SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
L
Linus Torvalds 已提交
475
		reg_offset = 0;
476
		dma_bitmode = SONIC_BITMODE16;
L
Linus Torvalds 已提交
477 478 479 480 481 482
		break;
	default:
		printk(KERN_ERR "macsonic: WTF, id is %d\n", id);
		return -ENODEV;
	}

483 484
	/* Danger!  My arms are flailing wildly!  You *must* set lp->reg_offset
	 * and dev->base_addr before using SONIC_READ() or SONIC_WRITE() */
L
Linus Torvalds 已提交
485
	dev->base_addr = base_addr;
486 487
	lp->reg_offset = reg_offset;
	lp->dma_bitmode = dma_bitmode;
L
Linus Torvalds 已提交
488 489 490 491 492 493 494
	dev->irq = SLOT2IRQ(ndev->board->slot);

	if (!sonic_version_printed) {
		printk(KERN_INFO "%s", version);
		sonic_version_printed = 1;
	}
	printk(KERN_INFO "%s: %s in slot %X\n",
495
	       lp->device->bus_id, ndev->board->name, ndev->board->slot);
L
Linus Torvalds 已提交
496
	printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
497
	       lp->device->bus_id, SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset);
L
Linus Torvalds 已提交
498

499 500 501 502
#if 0 /* This is sometimes useful to find out how MacOS configured the card. */
	printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id,
	       SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff);
#endif
L
Linus Torvalds 已提交
503 504

	/* Software reset, then initialize control registers. */
505 506 507 508 509 510
	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
	SONIC_WRITE(SONIC_DCR, sonic_dcr | (dma_bitmode ? SONIC_DCR_DW : 0));
	/* This *must* be written back to in order to restore the
	 * extended programmable output bits, since it may not have been
	 * initialised since the hardware reset. */
	SONIC_WRITE(SONIC_DCR2, 0);
L
Linus Torvalds 已提交
511 512

	/* Clear *and* disable interrupts to be on the safe side */
513 514
	SONIC_WRITE(SONIC_IMR, 0);
	SONIC_WRITE(SONIC_ISR, 0x7fff);
L
Linus Torvalds 已提交
515 516 517 518 519

	/* Now look for the MAC address. */
	if (mac_nubus_sonic_ethernet_addr(dev, prom_addr, id) != 0)
		return -ENODEV;

520 521 522 523
	/* Shared init code */
	return macsonic_init(dev);
}

524
static int __init mac_sonic_probe(struct platform_device *device)
525 526 527 528 529 530 531 532 533 534 535
{
	struct net_device *dev;
	struct sonic_local *lp;
	int err;
	int i;

	dev = alloc_etherdev(sizeof(struct sonic_local));
	if (!dev)
		return -ENOMEM;

	lp = netdev_priv(dev);
536 537
	lp->device = &device->dev;
	SET_NETDEV_DEV(dev, &device->dev);
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
 	SET_MODULE_OWNER(dev);

	/* This will catch fatal stuff like -ENOMEM as well as success */
	err = mac_onboard_sonic_probe(dev);
	if (err == 0)
		goto found;
	if (err != -ENODEV)
		goto out;
	err = mac_nubus_sonic_probe(dev);
	if (err)
		goto out;
found:
	err = register_netdev(dev);
	if (err)
		goto out;

	printk("%s: MAC ", dev->name);
L
Linus Torvalds 已提交
555 556 557 558 559 560 561
	for (i = 0; i < 6; i++) {
		printk("%2.2x", dev->dev_addr[i]);
		if (i < 5)
			printk(":");
	}
	printk(" IRQ %d\n", dev->irq);

562
	return 0;
L
Linus Torvalds 已提交
563

564 565
out:
	free_netdev(dev);
L
Linus Torvalds 已提交
566

567 568 569 570 571
	return err;
}

MODULE_DESCRIPTION("Macintosh SONIC ethernet driver");
module_param(sonic_debug, int, 0);
L
Linus Torvalds 已提交
572 573
MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");

574 575 576 577
#define SONIC_IRQ_FLAG IRQ_FLG_FAST

#include "sonic.c"

578
static int __devexit mac_sonic_device_remove (struct platform_device *device)
L
Linus Torvalds 已提交
579
{
580
	struct net_device *dev = platform_get_drvdata(device);
581 582 583 584 585 586 587
	struct sonic_local* lp = netdev_priv(dev);

	unregister_netdev (dev);
	dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
	                  lp->descriptors, lp->descriptors_laddr);
	free_netdev (dev);

L
Linus Torvalds 已提交
588 589 590
	return 0;
}

591
static struct platform_driver mac_sonic_driver = {
592 593
	.probe  = mac_sonic_probe,
	.remove = __devexit_p(mac_sonic_device_remove),
594 595 596
	.driver	= {
		.name = mac_sonic_string,
	},
597 598 599 600 601
};

static int __init mac_sonic_init_module(void)
{
	int err;
L
Linus Torvalds 已提交
602

603
	if ((err = platform_driver_register(&mac_sonic_driver))) {
604 605 606
		printk(KERN_ERR "Driver registration failed\n");
		return err;
	}
L
Linus Torvalds 已提交
607

R
Russell King 已提交
608 609
	mac_sonic_device = platform_device_alloc(mac_sonic_string, 0);
	if (!mac_sonic_device) {
610 611
		goto out_unregister;
	}
L
Linus Torvalds 已提交
612

R
Russell King 已提交
613 614
	if (platform_device_add(mac_sonic_device)) {
		platform_device_put(mac_sonic_device);
615 616 617 618 619 620
		mac_sonic_device = NULL;
	}

	return 0;

out_unregister:
621
	platform_driver_unregister(&mac_sonic_driver);
622 623 624 625 626 627

	return -ENOMEM;
}

static void __exit mac_sonic_cleanup_module(void)
{
628
	platform_driver_unregister(&mac_sonic_driver);
629 630 631 632 633 634 635 636 637

	if (mac_sonic_device) {
		platform_device_unregister(mac_sonic_device);
		mac_sonic_device = NULL;
	}
}

module_init(mac_sonic_init_module);
module_exit(mac_sonic_cleanup_module);