⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myri_sbus.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct net_device *dev = neigh->dev;	if (type == __constant_htons(ETH_P_802_3))		return -1;	/* Refill MyriNet padding identifiers, this is just being anal. */	pad[0] = MYRI_PAD_LEN;	pad[1] = 0xab;	eth->h_proto = type;	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);	memcpy(eth->h_dest, neigh->ha, dev->addr_len);	hh->hh_len = 16;	return 0;}/* Called by Address Resolution module to notify changes in address. */void myri_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr){	memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);}static int myri_change_mtu(struct net_device *dev, int new_mtu){	if ((new_mtu < (ETH_HLEN + MYRI_PAD_LEN)) || (new_mtu > MYRINET_MTU))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}static struct net_device_stats *myri_get_stats(struct net_device *dev){ return &(((struct myri_eth *)dev->priv)->enet_stats); }#define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */#define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */static void myri_set_multicast(struct net_device *dev){	/* Do nothing, all MyriCOM nodes transmit multicast frames	 * as broadcast packets...	 */}static inline void set_boardid_from_idprom(struct myri_eth *mp, int num){	mp->eeprom.id[0] = 0;	mp->eeprom.id[1] = idprom->id_machtype;	mp->eeprom.id[2] = (idprom->id_sernum >> 16) & 0xff;	mp->eeprom.id[3] = (idprom->id_sernum >> 8) & 0xff;	mp->eeprom.id[4] = (idprom->id_sernum >> 0) & 0xff;	mp->eeprom.id[5] = num;}static inline void determine_reg_space_size(struct myri_eth *mp){	switch(mp->eeprom.cpuvers) {	case CPUVERS_2_3:	case CPUVERS_3_0:	case CPUVERS_3_1:	case CPUVERS_3_2:		mp->reg_size = (3 * 128 * 1024) + 4096;		break;	case CPUVERS_4_0:	case CPUVERS_4_1:		mp->reg_size = ((4096<<1) + mp->eeprom.ramsz);		break;	case CPUVERS_4_2:	case CPUVERS_5_0:	default:		printk("myricom: AIEEE weird cpu version %04x assuming pre4.0\n",		       mp->eeprom.cpuvers);		mp->reg_size = (3 * 128 * 1024) + 4096;	};}#ifdef DEBUG_DETECTstatic void dump_eeprom(struct myri_eth *mp){	printk("EEPROM: clockval[%08x] cpuvers[%04x] "	       "id[%02x,%02x,%02x,%02x,%02x,%02x]\n",	       mp->eeprom.cval, mp->eeprom.cpuvers,	       mp->eeprom.id[0], mp->eeprom.id[1], mp->eeprom.id[2],	       mp->eeprom.id[3], mp->eeprom.id[4], mp->eeprom.id[5]);	printk("EEPROM: ramsz[%08x]\n", mp->eeprom.ramsz);	printk("EEPROM: fvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",	       mp->eeprom.fvers[0], mp->eeprom.fvers[1], mp->eeprom.fvers[2],	       mp->eeprom.fvers[3], mp->eeprom.fvers[4], mp->eeprom.fvers[5],	       mp->eeprom.fvers[6], mp->eeprom.fvers[7]);	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",	       mp->eeprom.fvers[8], mp->eeprom.fvers[9], mp->eeprom.fvers[10],	       mp->eeprom.fvers[11], mp->eeprom.fvers[12], mp->eeprom.fvers[13],	       mp->eeprom.fvers[14], mp->eeprom.fvers[15]);	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",	       mp->eeprom.fvers[16], mp->eeprom.fvers[17], mp->eeprom.fvers[18],	       mp->eeprom.fvers[19], mp->eeprom.fvers[20], mp->eeprom.fvers[21],	       mp->eeprom.fvers[22], mp->eeprom.fvers[23]);	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",	       mp->eeprom.fvers[24], mp->eeprom.fvers[25], mp->eeprom.fvers[26],	       mp->eeprom.fvers[27], mp->eeprom.fvers[28], mp->eeprom.fvers[29],	       mp->eeprom.fvers[30], mp->eeprom.fvers[31]);	printk("EEPROM: mvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",	       mp->eeprom.mvers[0], mp->eeprom.mvers[1], mp->eeprom.mvers[2],	       mp->eeprom.mvers[3], mp->eeprom.mvers[4], mp->eeprom.mvers[5],	       mp->eeprom.mvers[6], mp->eeprom.mvers[7]);	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",	       mp->eeprom.mvers[8], mp->eeprom.mvers[9], mp->eeprom.mvers[10],	       mp->eeprom.mvers[11], mp->eeprom.mvers[12], mp->eeprom.mvers[13],	       mp->eeprom.mvers[14], mp->eeprom.mvers[15]);	printk("EEPROM: dlval[%04x] brd_type[%04x] bus_type[%04x] prod_code[%04x]\n",	       mp->eeprom.dlval, mp->eeprom.brd_type, mp->eeprom.bus_type,	       mp->eeprom.prod_code);	printk("EEPROM: serial_num[%08x]\n", mp->eeprom.serial_num);}#endifstatic int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, int num){	static unsigned version_printed = 0;	struct myri_eth *mp;	unsigned char prop_buf[32];	int i;	DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num));	dev = init_etherdev(0, sizeof(struct myri_eth));	if (version_printed++ == 0)		printk(version);	printk("%s: MyriCOM MyriNET Ethernet ", dev->name);	mp = (struct myri_eth *) dev->priv;	mp->myri_sdev = sdev;	/* Clean out skb arrays. */	for (i = 0; i < (RX_RING_SIZE + 1); i++)		mp->rx_skbs[i] = NULL;	for (i = 0; i < TX_RING_SIZE; i++)		mp->tx_skbs[i] = NULL;	/* First check for EEPROM information. */	i = prom_getproperty(sdev->prom_node, "myrinet-eeprom-info",			     (char *)&mp->eeprom, sizeof(struct myri_eeprom));	DET(("prom_getprop(myrinet-eeprom-info) returns %d\n", i));	if (i == 0 || i == -1) {		/* No eeprom property, must cook up the values ourselves. */		DET(("No EEPROM: "));		mp->eeprom.bus_type = BUS_TYPE_SBUS;		mp->eeprom.cpuvers = prom_getintdefault(sdev->prom_node,"cpu_version",0);		mp->eeprom.cval = prom_getintdefault(sdev->prom_node,"clock_value",0);		mp->eeprom.ramsz = prom_getintdefault(sdev->prom_node,"sram_size",0);		DET(("cpuvers[%d] cval[%d] ramsz[%d]\n", mp->eeprom.cpuvers,		     mp->eeprom.cval, mp->eeprom.ramsz));		if (mp->eeprom.cpuvers == 0) {			DET(("EEPROM: cpuvers was zero, setting to %04x\n",CPUVERS_2_3));			mp->eeprom.cpuvers = CPUVERS_2_3;		}		if (mp->eeprom.cpuvers < CPUVERS_3_0) {			DET(("EEPROM: cpuvers < CPUVERS_3_0, clockval set to zero.\n"));			mp->eeprom.cval = 0;		}		if (mp->eeprom.ramsz == 0) {			DET(("EEPROM: ramsz == 0, setting to 128k\n"));			mp->eeprom.ramsz = (128 * 1024);		}		i = prom_getproperty(sdev->prom_node, "myrinet-board-id",				     &prop_buf[0], 10);		DET(("EEPROM: prom_getprop(myrinet-board-id) returns %d\n", i));		if ((i != 0) && (i != -1))			memcpy(&mp->eeprom.id[0], &prop_buf[0], 6);		else			set_boardid_from_idprom(mp, num);		i = prom_getproperty(sdev->prom_node, "fpga_version",				     &mp->eeprom.fvers[0], 32);		DET(("EEPROM: prom_getprop(fpga_version) returns %d\n", i));		if (i == 0 || i == -1)			memset(&mp->eeprom.fvers[0], 0, 32);		if (mp->eeprom.cpuvers == CPUVERS_4_1) {			DET(("EEPROM: cpuvers CPUVERS_4_1, "));			if (mp->eeprom.ramsz == (128 * 1024)) {				DET(("ramsize 128k, setting to 256k, "));				mp->eeprom.ramsz = (256 * 1024);			}			if ((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){				DET(("changing cval from %08x to %08x ",				     mp->eeprom.cval, 0x50e450e4));				mp->eeprom.cval = 0x50e450e4;			}			DET(("\n"));		}	}#ifdef DEBUG_DETECT	dump_eeprom(mp);#endif	for (i = 0; i < 6; i++)		printk("%2.2x%c",		       dev->dev_addr[i] = mp->eeprom.id[i],		       i == 5 ? ' ' : ':');	printk("\n");	determine_reg_space_size(mp);	/* Map in the MyriCOM register/localram set. */	if (mp->eeprom.cpuvers < CPUVERS_4_0) {		/* XXX Makes no sense, if control reg is non-existant this		 * XXX driver cannot function at all... maybe pre-4.0 is		 * XXX only a valid version for PCI cards?  Ask feldy...		 */		DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));		mp->regs = sbus_ioremap(&sdev->resource[0], 0,					mp->reg_size, "MyriCOM Regs");		if (!mp->regs) {			printk("MyriCOM: Cannot map MyriCOM registers.\n");			return -ENODEV;		}		mp->lanai = (unsigned short *) (mp->regs + (256 * 1024));		mp->lanai3 = (unsigned int *) mp->lanai;		mp->lregs = (unsigned long) &mp->lanai[0x10000];	} else {		DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));		mp->cregs = sbus_ioremap(&sdev->resource[0], 0,					 PAGE_SIZE, "MyriCOM Control Regs");		mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024),					 PAGE_SIZE, "MyriCOM LANAI Regs");		mp->lanai = (unsigned short *)			sbus_ioremap(&sdev->resource[0], (512 * 1024),				     mp->eeprom.ramsz, "MyriCOM SRAM");		mp->lanai3 = (unsigned int *) mp->lanai;	}	DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n",	     mp->cregs, mp->lregs, mp->lanai, mp->lanai3));	if (mp->eeprom.cpuvers >= CPUVERS_4_0)		mp->shmem_base = 0xf000;	else		mp->shmem_base = 0x8000;	DET(("Shared memory base is %04x, ", mp->shmem_base));	mp->shmem = (struct myri_shmem *) &mp->lanai[mp->shmem_base];	DET(("shmem mapped at %p\n", mp->shmem));	mp->rqack	= &mp->shmem->channel.recvqa;	mp->rq		= &mp->shmem->channel.recvq;	mp->sq		= &mp->shmem->channel.sendq;	/* Reset the board. */	DET(("Resetting LANAI\n"));	myri_reset_off(mp->lregs, mp->cregs);	myri_reset_on(mp->cregs);	/* Turn IRQ's off. */	myri_disable_irq(mp->lregs, mp->cregs);	/* Reset once more. */	myri_reset_on(mp->cregs);	/* Get the supported DVMA burst sizes from our SBUS. */	mp->myri_bursts = prom_getintdefault(mp->myri_sdev->bus->prom_node,					     "burst-sizes", 0x00);	if (!sbus_can_burst64(sdev))		mp->myri_bursts &= ~(DMA_BURST64);	DET(("MYRI bursts %02x\n", mp->myri_bursts));	/* Encode SBUS interrupt level in second control register. */	i = prom_getint(sdev->prom_node, "interrupts");	if (i == 0)		i = 4;	DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",	     i, (1 << i)));	sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);	mp->dev = dev;	dev->open = &myri_open;	dev->stop = &myri_close;	dev->hard_start_xmit = &myri_start_xmit;	dev->tx_timeout = &myri_tx_timeout;	dev->watchdog_timeo = 5*HZ;	dev->get_stats = &myri_get_stats;	dev->set_multicast_list = &myri_set_multicast;	dev->irq = sdev->irqs[0];	/* Register interrupt handler now. */	DET(("Requesting MYRIcom IRQ line.\n"));	if (request_irq(dev->irq, &myri_interrupt,			SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) {		printk("MyriCOM: Cannot register interrupt handler.\n");		return -ENODEV;	}	DET(("ether_setup()\n"));	ether_setup(dev);	dev->mtu		= MYRINET_MTU;	dev->change_mtu		= myri_change_mtu;	dev->hard_header	= myri_header;	dev->rebuild_header	= myri_rebuild_header;	dev->hard_header_len	= (ETH_HLEN + MYRI_PAD_LEN);	dev->hard_header_cache 	= myri_header_cache;	dev->header_cache_update= myri_header_cache_update;	/* Load code onto the LANai. */	DET(("Loading LANAI firmware\n"));	myri_load_lanai(mp);#ifdef MODULE	dev->ifindex = dev_new_index();	mp->next_module = root_myri_dev;	root_myri_dev = mp;#endif	return 0;}static int __init myri_sbus_match(struct sbus_dev *sdev){	char *name = sdev->prom_name;	if (!strcmp(name, "MYRICOM,mlanai") ||	    !strcmp(name, "myri"))		return 1;	return 0;}static int __init myri_sbus_probe(void){	struct net_device *dev = NULL;	struct sbus_bus *bus;	struct sbus_dev *sdev = 0;	static int called = 0;	int cards = 0, v;#ifdef MODULE	root_myri_dev = NULL;#endif	if (called)		return -ENODEV;	called++;	for_each_sbus(bus) {		for_each_sbusdev(sdev, bus) {			if (cards)				dev = NULL;			if (myri_sbus_match(sdev)) {				cards++;				DET(("Found myricom myrinet as %s\n", sdev->prom_name));				if ((v = myri_ether_init(dev, sdev, (cards - 1))))					return v;			}		}	}	if (!cards)		return -ENODEV;	return 0;}static void __exit myri_sbus_cleanup(void){#ifdef MODULE	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */	while (root_myri_dev) {		struct myri_eth *next = root_myri_dev->next_module;		unregister_netdev(root_myri_dev->dev);		kfree(root_myri_dev->dev);		root_myri_dev = next;	}#endif /* MODULE */}module_init(myri_sbus_probe);module_exit(myri_sbus_cleanup);

⌨️ 快捷键说明

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