macsonic.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 657 行 · 第 1/2 页

C
657
字号
		if (once_is_more_than_enough)		return -ENODEV;	once_is_more_than_enough = 1;	if (!MACH_IS_MAC)		return -ENODEV;	printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");	if (macintosh_config->ether_type != MAC_ETHER_SONIC)	{		printk("none.\n");		return -ENODEV;	}	/* 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 ||	    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;		}	}	printk("yes\n");		/* Danger!  My arms are flailing wildly!  You *must* set this           before using sonic_read() */	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",	       dev->name, dev->base_addr);	/* Now do a song and dance routine in an attempt to determine           the bus width */	/* The PowerBook's SONIC is 16 bit always. */	if (macintosh_config->ident == MAC_MODEL_PB520) {		reg_offset = 0;		dma_bitmode = 0;	} else if (macintosh_config->ident == MAC_MODEL_C610) {		reg_offset = 0;		dma_bitmode = 1;	} else {		/* Some of the comm-slot cards are 16 bit.  But some                   of them are not.  The 32-bit cards use offset 2 and                   pad with zeroes or sometimes ones (I think...)                   Therefore, if we try offset 0 and get a silicon                   revision of 0, we assume 16 bit. */		int sr;		/* Technically this is not necessary since we zeroed                   it above */		reg_offset = 0;		dma_bitmode = 0;		sr = sonic_read(dev, SONIC_SR);		if (sr == 0 || sr == 0xffff) {			reg_offset = 2;			/* 83932 is 0x0004, 83934 is 0x0100 or 0x0101 */			sr = sonic_read(dev, SONIC_SR);			dma_bitmode = 1;					}		printk(KERN_INFO		       "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",		       dev->name, sr, dma_bitmode?32:16, reg_offset);	}		/* this carries my sincere apologies -- by the time I got to updating	   the driver, support for "reg_offsets" appeares nowhere in the sonic	   code, going back for over a year.  Fortunately, my Mac does't seem	   to use whatever this was.	   If you know how this is supposed to be implemented, either fix it,	   or contact me (sammy@oh.verio.com) to explain what it is. --Sam */	   	if(reg_offset) {		printk("%s: register offset unsupported.  please fix this if you know what it is.\n", dev->name);		return -ENODEV;	}		/* Software reset, then initialize control registers. */	sonic_write(dev, SONIC_CMD, SONIC_CR_RST);	sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS |		    SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS |		    (dma_bitmode ? SONIC_DCR_DW : 0));	/* This *must* be written back to in order to restore the           extended programmable output bits */	sonic_write(dev, SONIC_DCR2, 0);	/* Clear *and* disable interrupts to be on the safe side */	sonic_write(dev, SONIC_ISR,0x7fff);	sonic_write(dev, SONIC_IMR,0);	/* Now look for the MAC address. */	if (mac_onboard_sonic_ethernet_addr(dev) != 0)		return -ENODEV;	printk(KERN_INFO "MAC ");	for (i = 0; i < 6; i++) {		printk("%2.2x", dev->dev_addr[i]);		if (i < 5)			printk(":");	}	printk(" IRQ %d\n", dev->irq);	/* 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);	/* For now we are going to assume that they're all bit-reversed */	bit_reverse_addr(dev->dev_addr);	return 0;}int __init macsonic_ident(struct nubus_dev* ndev){	if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC && 	    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;	}	return -1;}int __init mac_nubus_sonic_probe(struct net_device* dev){	static int slots;	struct nubus_dev* ndev = NULL;	unsigned long base_addr, prom_addr;	u16 sonic_dcr;	int id;	int i;	int dma_bitmode;	/* 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;		sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1			| SONIC_DCR_TFT0;		reg_offset = 2;		dma_bitmode = 1;		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;		dma_bitmode = 1;		break;	case MACSONIC_APPLE16:		base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;		prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;		sonic_dcr = SONIC_DCR_EXBUS 			| SONIC_DCR_RFT1 | SONIC_DCR_TFT0			| SONIC_DCR_PO1 | SONIC_DCR_BMS; 		reg_offset = 0;		dma_bitmode = 0;		break;	case MACSONIC_DAYNALINK:		base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;		prom_addr = ndev->board->slot_addr + DAYNALINK_PROM_BASE;		sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0			| SONIC_DCR_PO1 | SONIC_DCR_BMS; 		reg_offset = 0;		dma_bitmode = 0;		break;	case MACSONIC_DAYNA:		base_addr = ndev->board->slot_addr + DAYNA_SONIC_REGISTERS;		prom_addr = ndev->board->slot_addr + DAYNA_SONIC_MAC_ADDR;		sonic_dcr = SONIC_DCR_BMS			| SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;		reg_offset = 0;		dma_bitmode = 0;		break;	default:		printk(KERN_ERR "macsonic: WTF, id is %d\n", id);		return -ENODEV;	}	/* Danger!  My arms are flailing wildly!  You *must* set this           before using sonic_read() */	dev->base_addr = base_addr;	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",	       dev->name, ndev->board->name, ndev->board->slot);	printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",	       dev->name, sonic_read(dev, SONIC_SR), dma_bitmode?32:16, reg_offset);	if(reg_offset) {		printk("%s: register offset unsupported.  please fix this if you know what it is.\n", dev->name);		return -ENODEV;	}	/* Software reset, then initialize control registers. */	sonic_write(dev, SONIC_CMD, SONIC_CR_RST);	sonic_write(dev, SONIC_DCR, sonic_dcr		    | (dma_bitmode ? SONIC_DCR_DW : 0));	/* Clear *and* disable interrupts to be on the safe side */	sonic_write(dev, SONIC_ISR,0x7fff);	sonic_write(dev, SONIC_IMR,0);	/* Now look for the MAC address. */	if (mac_nubus_sonic_ethernet_addr(dev, prom_addr, id) != 0)		return -ENODEV;	printk(KERN_INFO "MAC ");	for (i = 0; i < 6; i++) {		printk("%2.2x", dev->dev_addr[i]);		if (i < 5)			printk(":");	}	printk(" IRQ %d\n", dev->irq);	/* Shared init code */	return macsonic_init(dev);}#ifdef MODULEstatic struct net_device *dev_macsonic;MODULE_PARM(sonic_debug, "i");MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");intinit_module(void){        dev_macsonic = macsonic_probe(-1);	if (IS_ERR(dev_macsonic)) {                printk(KERN_WARNING "macsonic.c: No card found\n");		return PTR_ERR(dev_macsonic);	}	return 0;}voidcleanup_module(void){	unregister_netdev(dev_macsonic);	kfree(dev_macsonic->priv);	free_netdev(dev_macsonic);}#endif /* MODULE */#define vdma_alloc(foo, bar) ((u32)foo)#define vdma_free(baz)#define sonic_chiptomem(bat) (bat)#define PHYSADDR(quux) (quux)#define sonic_request_irq       request_irq#define sonic_free_irq          free_irq#include "sonic.c"/* * Local variables: *  compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o macsonic.o macsonic.c" *  version-control: t *  kept-new-versions: 5 *  c-indent-level: 8 *  tab-width: 8 * End: * */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?