/***
 *	rt_register_rtnetdev:	register a new rtnet_device (linux-like)
 *	@rtdev:			the device
 */
int rt_register_rtnetdev(struct rtnet_device *rtdev)
{
	struct net_device *d, **dp, *dev = dev_get_by_rtdev(rtdev);

	rt_printk("RTnet: rt_register_netdevice(%s)\n", dev->name);

	dev->iflink = -1;
	/* Init, if this function is available */
	if ( (dev->init) && (dev->init(dev)) ) {
		return -EIO;
	}
	dev->ifindex = dev_new_index();
	if (dev->iflink == -1)
		dev->iflink = dev->ifindex;

	/* Check for existence, and append to tail of chain */
	for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
		if ( (d==dev) || (!strcmp(d->name, dev->name)) ) {
			return -EEXIST;
		}
	}

	/*
	 *	Default initial state at registry is that the
	 *	device is present.
	 */
	set_bit(__LINK_STATE_PRESENT, &dev->state);
	dev->next = NULL;

	/* insert to list */
	write_lock(&dev_base_lock);
	*dp = dev;
	dev->deadbeaf = 0;
	write_unlock(&dev_base_lock);

	return 0;
}
Beispiel #2
0
static 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;
}
Beispiel #3
0
/* Initialise a single lance board at the given select code */
static int __init hplance_init(struct net_device *dev, int scode)
{
        /* const char *name = dio_scodetoname(scode); */
        static const char name[] = "HP LANCE";
        void *va = dio_scodetoviraddr(scode);
        struct hplance_private *lp;
        int i;
        
#ifdef MODULE
	dev = init_etherdev(0, sizeof(struct hplance_private));
	if (!dev)
		return -ENOMEM;
#else
	dev->priv = kmalloc(sizeof(struct hplance_private), GFP_KERNEL);
	if (dev->priv == NULL)
		return -ENOMEM;
	memset(dev->priv, 0, sizeof(struct hplance_private));
#endif
	SET_MODULE_OWNER(dev);

        printk("%s: HP LANCE; select code %d, addr", dev->name, scode);

        /* reset the board */
        writeb(0xff,va+DIO_IDOFF);
        udelay(100);                              /* ariba! ariba! udelay! udelay! */

        /* Fill the dev fields */
        dev->base_addr = (unsigned long)va;
        dev->open = &hplance_open;
        dev->stop = &hplance_close;
        dev->hard_start_xmit = &lance_start_xmit;
        dev->get_stats = &lance_get_stats;
        dev->set_multicast_list = &lance_set_multicast;
        dev->dma = 0;
        
        for (i=0; i<6; i++)
        {
                /* The NVRAM holds our ethernet address, one nibble per byte,
                 * at bytes NVRAMOFF+1,3,5,7,9...
                 */
                dev->dev_addr[i] = ((readb(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
                        | (readb(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
                printk("%c%2.2x", i == 0 ? ' ' : ':', dev->dev_addr[i]);
        }
        
        lp = (struct hplance_private *)dev->priv;
        lp->lance.name = (char*)name;                   /* discards const, shut up gcc */
        lp->lance.ll = (struct lance_regs *)(va + HPLANCE_REGOFF);
        lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
        lp->lance.lance_init_block = 0;                 /* LANCE addr of same RAM */
        lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
        lp->lance.irq = dio_scodetoipl(scode);
        lp->lance.writerap = hplance_writerap;
        lp->lance.writerdp = hplance_writerdp;
        lp->lance.readrdp = hplance_readrdp;
        lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
        lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
        lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
        lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
        lp->scode = scode;
	lp->base = va;
        ether_setup(dev);
	printk(", irq %d\n", lp->lance.irq);

#ifdef MODULE
        dev->ifindex = dev_new_index();
        lp->next_module = root_hplance_dev;
        root_hplance_dev = lp;
#endif /* MODULE */

        dio_config_board(scode);                  /* tell bus scanning code this one's taken */
        return 0;
}