コード例 #1
0
static int mca_bus_match (struct device *dev, struct device_driver *drv)
{
	struct mca_device *mca_dev = to_mca_device (dev);
	struct mca_driver *mca_drv = to_mca_driver (drv);
	const unsigned short *mca_ids = mca_drv->id_table;
	int i = 0;

	if (mca_ids) {
		for(i = 0; mca_ids[i]; i++) {
			if (mca_ids[i] == mca_dev->pos_id) {
				mca_dev->index = i;
				return 1;
			}
		}
	}
	/* If the integrated id is present, treat it as though it were an
	 * additional id in the id_table (it can't be because by definition,
	 * integrated id's overflow a short */
	if (mca_drv->integrated_id && mca_dev->pos_id ==
	    mca_drv->integrated_id) {
		mca_dev->index = i;
		return 1;
	}
	return 0;
}
コード例 #2
0
ファイル: mca-legacy.c プロジェクト: 274914765/C
static int mca_find_device_by_slot_callback(struct device *dev, void *data)
{
    struct mca_find_device_by_slot_info *info = data;
    struct mca_device *mca_dev = to_mca_device(dev);

    if(mca_dev->slot == info->slot)
        info->mca_dev = mca_dev;

    return 0;
}
コード例 #3
0
ファイル: mca-bus.c プロジェクト: chm088/linux-2.6.18
static ssize_t mca_show_pos(struct device *dev, struct device_attribute *attr, char *buf)
{
	/* enough for 8 two byte hex chars plus space and new line */
	int j, len=0;
	struct mca_device *mca_dev = to_mca_device(dev);

	for(j=0; j<8; j++)
		len += sprintf(buf+len, "%02x ", mca_dev->pos[j]);
	/* change last trailing space to new line */
	buf[len-1] = '\n';
	return len;
}
コード例 #4
0
ファイル: mca-bus.c プロジェクト: chm088/linux-2.6.18
static ssize_t mca_show_pos_id(struct device *dev, struct device_attribute *attr, char *buf)
{
	/* four digits, \n and trailing \0 */
	struct mca_device *mca_dev = to_mca_device(dev);
	int len;

	if(mca_dev->pos_id < MCA_DUMMY_POS_START)
		len = sprintf(buf, "%04x\n", mca_dev->pos_id);
	else
		len = sprintf(buf, "none\n");
	return len;
}
コード例 #5
0
static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
{
	struct mca_device *mca_dev = to_mca_device(dev);
	unsigned char pos5;

	pos5 = mca_device_read_pos(mca_dev, 5);

	if (!(pos5 & 0x80)) {
		
		mca_handle_nmi_device(mca_dev, !(pos5 & 0x40));
		return 1;
	}
	return 0;
}
コード例 #6
0
ファイル: ibmlana.c プロジェクト: E-LLP/n900
static int ibmlana_remove_one(struct device *kdev)
{
	struct mca_device *mdev = to_mca_device(kdev);
	struct net_device *dev = dev_get_drvdata(kdev);
	ibmlana_priv *priv = netdev_priv(dev);

	unregister_netdev(dev);
	/*DeinitBoard(dev); */
	release_region(dev->base_addr, IBM_LANA_IORANGE);
	mca_device_set_claim(mdev, 0);
	iounmap(priv->base);
	free_netdev(dev);
	return 0;
}
コード例 #7
0
ファイル: mca-legacy.c プロジェクト: 274914765/C
/* The purpose of this iterator is to loop over all the devices and
 * find the one with the smallest slot number that's just greater than
 * or equal to the required slot with a matching id */
static int mca_find_adapter_callback(struct device *dev, void *data)
{
    struct mca_find_adapter_info *info = data;
    struct mca_device *mca_dev = to_mca_device(dev);

    if(mca_dev->pos_id != info->id)
        return 0;

    if(mca_dev->slot < info->slot)
        return 0;

    if(!info->mca_dev || info->mca_dev->slot >= mca_dev->slot)
        info->mca_dev = mca_dev;

    return 0;
}
コード例 #8
0
static int ultramca_remove(struct device *gen_dev)
{
	struct mca_device *mca_dev = to_mca_device(gen_dev);
	struct net_device *dev = (struct net_device *)gen_dev->driver_data;

	if (dev) {
		/* NB: ultra_close_card() does free_irq */
		int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;

		unregister_netdev(dev);
		mca_device_set_claim(mca_dev, 0);
		release_region(ioaddr, ULTRA_IO_EXTENT);
		free_netdev(dev);
	}
	return 0;
}
コード例 #9
0
ファイル: mca.c プロジェクト: sarnobat/knoppix
static int mca_handle_nmi_callback(struct device *dev, void *data)
{
	struct mca_device *mca_dev = to_mca_device(dev);
	unsigned char pos5;

	pos5 = mca_device_read_pos(mca_dev, 5);

	if(!(pos5 & 0x80)) {
		/* Bit 7 of POS 5 is reset when this adapter has a hardware
		 * error. Bit 7 it reset if there's error information
		 * available in POS 6 and 7.
		 */
		mca_handle_nmi_device(mca_dev, !(pos5 & 0x40));
		return 1;
	}
	return 0;
}
コード例 #10
0
ファイル: mca-bus.c プロジェクト: chm088/linux-2.6.18
static int mca_bus_match (struct device *dev, struct device_driver *drv)
{
	struct mca_device *mca_dev = to_mca_device (dev);
	struct mca_driver *mca_drv = to_mca_driver (drv);
	const short *mca_ids = mca_drv->id_table;
	int i;

	if (!mca_ids)
		return 0;

	for(i = 0; mca_ids[i]; i++) {
		if (mca_ids[i] == mca_dev->pos_id) {
			mca_dev->index = i;
			return 1;
		}
	}

	return 0;
}
コード例 #11
0
ファイル: NCR_D700.c プロジェクト: rrowicki/Chrono_Kernel-1
/* Detect a D700 card.  Note, because of the setup --- the chips are
 * essentially connectecd to the MCA bus independently, it is easier
 * to set them up as two separate host adapters, rather than one
 * adapter with two channels */
static int __devinit
NCR_D700_probe(struct device *dev)
{
	struct NCR_D700_private *p;
	int differential;
	static int banner = 1;
	struct mca_device *mca_dev = to_mca_device(dev);
	int slot = mca_dev->slot;
	int found = 0;
	int irq, i;
	int pos3j, pos3k, pos3a, pos3b, pos4;
	__u32 base_addr, offset_addr;

	/* enable board interrupt */
	pos4 = mca_device_read_pos(mca_dev, 4);
	pos4 |= 0x4;
	mca_device_write_pos(mca_dev, 4, pos4);

	mca_device_write_pos(mca_dev, 6, 9);
	pos3j = mca_device_read_pos(mca_dev, 3);
	mca_device_write_pos(mca_dev, 6, 10);
	pos3k = mca_device_read_pos(mca_dev, 3);
	mca_device_write_pos(mca_dev, 6, 0);
	pos3a = mca_device_read_pos(mca_dev, 3);
	mca_device_write_pos(mca_dev, 6, 1);
	pos3b = mca_device_read_pos(mca_dev, 3);

	base_addr = ((pos3j << 8) | pos3k) & 0xfffffff0;
	offset_addr = ((pos3a << 8) | pos3b) & 0xffffff70;

	irq = (pos4 & 0x3) + 11;
	if(irq >= 13)
		irq++;
	if(banner) {
//		printk(KERN_NOTICE "NCR D700: Driver Version " NCR_D700_VERSION "\n"
//		       "NCR D700:  Copyright (c) 2001 by [email protected]\n"
;
		banner = 0;
	}
	/* now do the bus related transforms */
	irq = mca_device_transform_irq(mca_dev, irq);
	base_addr = mca_device_transform_ioport(mca_dev, base_addr);
	offset_addr = mca_device_transform_ioport(mca_dev, offset_addr);

;

	/*outb(BOARD_RESET, base_addr);*/

	/* clear any pending interrupts */
	(void)inb(base_addr + 0x08);
	/* get modctl, used later for setting diff bits */
	switch(differential = (inb(base_addr + 0x08) >> 6)) {
	case 0x00:
		/* only SIOP1 differential */
		differential = 0x02;
		break;
	case 0x01:
		/* Both SIOPs differential */
		differential = 0x03;
		break;
	case 0x03:
		/* No SIOPs differential */
		differential = 0x00;
		break;
	default:
//		printk(KERN_ERR "D700: UNEXPECTED DIFFERENTIAL RESULT 0x%02x\n",
;
		differential = 0x00;
		break;
	}

	p = kzalloc(sizeof(*p), GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	p->dev = dev;
	snprintf(p->name, sizeof(p->name), "D700(%s)", dev_name(dev));
	if (request_irq(irq, NCR_D700_intr, IRQF_SHARED, p->name, p)) {
;
		kfree(p);
		return -EBUSY;
	}
	/* plumb in both 700 chips */
	for (i = 0; i < 2; i++) {
		int err;

		if ((err = NCR_D700_probe_one(p, i, irq, slot,
					      offset_addr + (0x80 * i),
					      differential)) != 0)
//			printk("D700: SIOP%d: probe failed, error = %d\n",
;
		else
			found++;
	}

	if (!found) {
		kfree(p);
		return -ENODEV;
	}

	mca_device_set_claim(mca_dev, 1);
	mca_device_set_name(mca_dev, "NCR_D700");
	dev_set_drvdata(dev, p);
	return 0;
}
コード例 #12
0
static int __devinit
NCR_D700_probe(struct device *dev)
{
	struct NCR_D700_private *p;
	int differential;
	static int banner = 1;
	struct mca_device *mca_dev = to_mca_device(dev);
	int slot = mca_dev->slot;
	int found = 0;
	int irq, i;
	int pos3j, pos3k, pos3a, pos3b, pos4;
	__u32 base_addr, offset_addr;

	
	pos4 = mca_device_read_pos(mca_dev, 4);
	pos4 |= 0x4;
	mca_device_write_pos(mca_dev, 4, pos4);

	mca_device_write_pos(mca_dev, 6, 9);
	pos3j = mca_device_read_pos(mca_dev, 3);
	mca_device_write_pos(mca_dev, 6, 10);
	pos3k = mca_device_read_pos(mca_dev, 3);
	mca_device_write_pos(mca_dev, 6, 0);
	pos3a = mca_device_read_pos(mca_dev, 3);
	mca_device_write_pos(mca_dev, 6, 1);
	pos3b = mca_device_read_pos(mca_dev, 3);

	base_addr = ((pos3j << 8) | pos3k) & 0xfffffff0;
	offset_addr = ((pos3a << 8) | pos3b) & 0xffffff70;

	irq = (pos4 & 0x3) + 11;
	if(irq >= 13)
		irq++;
	if(banner) {
		printk(KERN_NOTICE "NCR D700: Driver Version " NCR_D700_VERSION "\n"
		       "NCR D700:  Copyright (c) 2001 by [email protected]\n"
		       "NCR D700:\n");
		banner = 0;
	}
	
	irq = mca_device_transform_irq(mca_dev, irq);
	base_addr = mca_device_transform_ioport(mca_dev, base_addr);
	offset_addr = mca_device_transform_ioport(mca_dev, offset_addr);

	printk(KERN_NOTICE "NCR D700: found in slot %d  irq = %d  I/O base = 0x%x\n", slot, irq, offset_addr);

	

	
	(void)inb(base_addr + 0x08);
	
	switch(differential = (inb(base_addr + 0x08) >> 6)) {
	case 0x00:
		
		differential = 0x02;
		break;
	case 0x01:
		
		differential = 0x03;
		break;
	case 0x03:
		
		differential = 0x00;
		break;
	default:
		printk(KERN_ERR "D700: UNEXPECTED DIFFERENTIAL RESULT 0x%02x\n",
		       differential);
		differential = 0x00;
		break;
	}

	p = kzalloc(sizeof(*p), GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	p->dev = dev;
	snprintf(p->name, sizeof(p->name), "D700(%s)", dev_name(dev));
	if (request_irq(irq, NCR_D700_intr, IRQF_SHARED, p->name, p)) {
		printk(KERN_ERR "D700: request_irq failed\n");
		kfree(p);
		return -EBUSY;
	}
	
	for (i = 0; i < 2; i++) {
		int err;

		if ((err = NCR_D700_probe_one(p, i, irq, slot,
					      offset_addr + (0x80 * i),
					      differential)) != 0)
			printk("D700: SIOP%d: probe failed, error = %d\n",
			       i, err);
		else
			found++;
	}

	if (!found) {
		kfree(p);
		return -ENODEV;
	}

	mca_device_set_claim(mca_dev, 1);
	mca_device_set_name(mca_dev, "NCR_D700");
	dev_set_drvdata(dev, p);
	return 0;
}
コード例 #13
0
ファイル: sim710.c プロジェクト: rrowicki/Chrono_Kernel-1
static __init int
sim710_mca_probe(struct device *dev)
{
	struct mca_device *mca_dev = to_mca_device(dev);
	int slot = mca_dev->slot;
	int pos[3];
	unsigned int base;
	int irq_vector;
	short id = sim710_mca_id_table[mca_dev->index];
	static int io_004f_by_pos[] = MCA_004F_IO_PORTS;
	static int irq_004f_by_pos[] = MCA_004F_IRQS;
	static int io_01bb_by_pos[] = MCA_01BB_IO_PORTS;
	static int irq_01bb_by_pos[] = MCA_01BB_IRQS;
	char *name;
	int clock;

	pos[0] = mca_device_read_stored_pos(mca_dev, 2);
	pos[1] = mca_device_read_stored_pos(mca_dev, 3);
	pos[2] = mca_device_read_stored_pos(mca_dev, 4);

	/*
	 * 01BB & 01BA port base by bits 7,6,5,4,3,2 in pos[2]
	 *
	 *    000000  <disabled>   001010  0x2800
	 *    000001  <invalid>    001011  0x2C00
	 *    000010  0x0800       001100  0x3000
	 *    000011  0x0C00       001101  0x3400
	 *    000100  0x1000       001110  0x3800
	 *    000101  0x1400       001111  0x3C00
	 *    000110  0x1800       010000  0x4000
	 *    000111  0x1C00       010001  0x4400
	 *    001000  0x2000       010010  0x4800
	 *    001001  0x2400       010011  0x4C00
	 *                         010100  0x5000
	 *
	 * 00F4 port base by bits 3,2,1 in pos[0]
	 *
	 *    000  <disabled>      001    0x200
	 *    010  0x300           011    0x400
	 *    100  0x500           101    0x600
	 *
	 * 01BB & 01BA IRQ is specified in pos[0] bits 7 and 6:
	 *
	 *    00   3               10   11
	 *    01   5               11   14
	 *
	 * 00F4 IRQ specified by bits 6,5,4 in pos[0]
	 *
	 *    100   5              101    9
	 *    110   14
	 */

	if (id == 0x01bb || id == 0x01ba) {
		base = io_01bb_by_pos[(pos[2] & 0xFC) >> 2];
		irq_vector =
			irq_01bb_by_pos[((pos[0] & 0xC0) >> 6)];

		clock = 50;
		if (id == 0x01bb)
			name = "NCR 3360/3430 SCSI SubSystem";
		else
			name = "NCR Dual SIOP SCSI Host Adapter Board";
	} else if ( id == 0x004f ) {
コード例 #14
0
int __init ultramca_probe(struct device *gen_dev)
{
	unsigned short ioaddr;
	struct net_device *dev;
	unsigned char reg4, num_pages;
	struct mca_device *mca_dev = to_mca_device(gen_dev);
	char slot = mca_dev->slot;
	unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff;
	int i, rc;
	int adapter = mca_dev->index;
	int tbase = 0;
	int tirq = 0;
	int base_addr = ultra_io[ultra_found];
	int irq = ultra_irq[ultra_found];

	if (base_addr || irq) {
		printk(KERN_INFO "Probing for SMC MCA adapter");
		if (base_addr) {
			printk(KERN_INFO " at I/O address 0x%04x%c",
			       base_addr, irq ? ' ' : '\n');
		}
		if (irq) {
			printk(KERN_INFO "using irq %d\n", irq);
		}
	}

	tirq = 0;
	tbase = 0;

	/* If we're trying to match a specificied irq or io address,
	 * we'll reject the adapter found unless it's the one we're
	 * looking for */

	pos2 = mca_device_read_stored_pos(mca_dev, 2); /* io_addr */
	pos3 = mca_device_read_stored_pos(mca_dev, 3); /* shared mem */
	pos4 = mca_device_read_stored_pos(mca_dev, 4); /* ROM bios addr range */
	pos5 = mca_device_read_stored_pos(mca_dev, 5); /* irq, media and RIPL */

	/* Test the following conditions:
	 * - If an irq parameter is supplied, compare it
	 *   with the irq of the adapter we found
	 * - If a base_addr paramater is given, compare it
	 *   with the base_addr of the adapter we found
	 * - Check that the irq and the base_addr of the
	 *   adapter we found is not already in use by
	 *   this driver
	 */

	switch (mca_dev->index) {
	case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
	case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
	case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
	case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
		{
			tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr;
			tirq  = irq_table[(pos5 & 0xc) >> 2].new_irq;
			break;
		}
	case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
	case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
	case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
	case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
		{
			tbase = ((pos2 & 0x0fe) * 0x10);
			tirq  = irq_table[(pos5 & 3)].old_irq;
			break;
		}
	}
	
	if(!tirq || !tbase 
	   || (irq && irq != tirq) 
	   || (base_addr && tbase != base_addr))
		/* FIXME: we're trying to force the ordering of the
		 * devices here, there should be a way of getting this
		 * to happen */
		return -ENXIO;

        /* Adapter found. */
	dev  = alloc_ei_netdev();
	if(!dev)
		return -ENODEV;

	SET_MODULE_OWNER(dev);
	SET_NETDEV_DEV(dev, gen_dev);
	mca_device_set_name(mca_dev, smc_mca_adapter_names[adapter]);
	mca_device_set_claim(mca_dev, 1);

	printk(KERN_INFO "smc_mca: %s found in slot %d\n",
		       smc_mca_adapter_names[adapter], slot + 1);

	ultra_found++;

	dev->base_addr = ioaddr = mca_device_transform_ioport(mca_dev, tbase);
	dev->irq       = mca_device_transform_irq(mca_dev, tirq);
	dev->mem_start = 0;
	num_pages      = 40;

	switch (adapter) {	/* card-# in const array above [hs] */
		case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
		case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
		{
			for (i = 0; i < 16; i++) { /* taking 16 counts
						    * up to 15 [hs] */
				if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) {
					dev->mem_start = (unsigned long)
					  mca_device_transform_memory(mca_dev, (void *)mem_table[i].mem_start);
					num_pages = mem_table[i].num_pages;
				}
			}
			break;
		}
		case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
		case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
		case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
		case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
		{
			dev->mem_start = (unsigned long)
			  mca_device_transform_memory(mca_dev, (void *)((pos3 & 0xfc) * 0x1000));
			num_pages = 0x40;
			break;
		}
		case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
		case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
		{
			/* courtesy of [email protected], pos3 indicates
			 * the index of the 0x2000 step.
			 * beware different number of pages [hs]
			 */
			dev->mem_start = (unsigned long) 
			  mca_device_transform_memory(mca_dev, (void *)(0xc0000 + (0x2000 * (pos3 & 0xf))));
			num_pages = 0x20 + (2 * (pos3 & 0x10));
			break;
		}
	}

	/* sanity check, shouldn't happen */
	if (dev->mem_start == 0) {
		rc = -ENODEV;
		goto err_unclaim;
	}

	if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) {
		rc = -ENODEV;
		goto err_unclaim;
	}

	reg4 = inb(ioaddr + 4) & 0x7f;
	outb(reg4, ioaddr + 4);

	printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x,", slot + 1, ioaddr);

	for (i = 0; i < 6; i++)
		printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));

	/* Switch from the station address to the alternate register set
	 * and read the useful registers there.
	 */

	outb(0x80 | reg4, ioaddr + 4);

	/* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot.
	 */

	outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);

	/* Switch back to the station address register set so that
	 * the MS-DOS driver can find the card after a warm boot.
	 */

	outb(reg4, ioaddr + 4);

	gen_dev->driver_data = dev;

	/* The 8390 isn't at the base address, so fake the offset
	 */

	dev->base_addr = ioaddr + ULTRA_NIC_OFFSET;

	ei_status.name = "SMC Ultra MCA";
	ei_status.word16 = 1;
	ei_status.tx_start_page = START_PG;
	ei_status.rx_start_page = START_PG + TX_PAGES;
	ei_status.stop_page = num_pages;

	ei_status.rmem_start = dev->mem_start + TX_PAGES * 256;
	dev->mem_end = ei_status.rmem_end =
	dev->mem_start + (ei_status.stop_page - START_PG) * 256;

	printk(", IRQ %d memory %#lx-%#lx.\n",
	dev->irq, dev->mem_start, dev->mem_end - 1);

	ei_status.reset_8390 = &ultramca_reset_8390;
	ei_status.block_input = &ultramca_block_input;
	ei_status.block_output = &ultramca_block_output;
	ei_status.get_8390_hdr = &ultramca_get_8390_hdr;

	ei_status.priv = slot;

	dev->open = &ultramca_open;
	dev->stop = &ultramca_close_card;
#ifdef CONFIG_NET_POLL_CONTROLLER
	dev->poll_controller = ei_poll;
#endif

	NS8390_init(dev, 0);

	rc = register_netdev(dev);
	if (rc)
		goto err_release_region;

	return 0;

err_release_region:
	release_region(ioaddr, ULTRA_IO_EXTENT);
err_unclaim:
	mca_device_set_claim(mca_dev, 0);
	free_netdev(dev);
	return rc;
}
コード例 #15
0
ファイル: ibmlana.c プロジェクト: E-LLP/n900
static int __devinit ibmlana_init_one(struct device *kdev)
{
	struct mca_device *mdev = to_mca_device(kdev);
	struct net_device *dev;
	int slot = mdev->slot, z, rc;
	int base = 0, irq = 0, iobase = 0, memlen = 0;
	ibmlana_priv *priv;
	ibmlana_medium medium;
	DECLARE_MAC_BUF(mac);

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

	dev->irq = ibmlana_irq;
	dev->base_addr = ibmlana_io;

	base = dev->mem_start;
	irq = dev->irq;

	/* deduce card addresses */
	getaddrs(mdev, &base, &memlen, &iobase, &irq, &medium);

	/* were we looking for something different ? */
	if (dev->irq && dev->irq != irq) {
		rc = -ENODEV;
		goto err_out;
	}
	if (dev->mem_start && dev->mem_start != base) {
		rc = -ENODEV;
		goto err_out;
	}

	/* announce success */
	printk(KERN_INFO "%s: IBM LAN Adapter/A found in slot %d\n", dev->name, slot + 1);

	/* try to obtain I/O range */
	if (!request_region(iobase, IBM_LANA_IORANGE, DRV_NAME)) {
		printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", DRV_NAME, iobase);
		startslot = slot + 1;
		rc = -EBUSY;
		goto err_out;
	}

	priv = netdev_priv(dev);
	priv->slot = slot;
	priv->realirq = mca_device_transform_irq(mdev, irq);
	priv->medium = medium;
	spin_lock_init(&priv->lock);

	/* set base + irq for this device (irq not allocated so far) */

	dev->irq = 0;
	dev->mem_start = base;
	dev->mem_end = base + memlen;
	dev->base_addr = iobase;

	priv->base = ioremap(base, memlen);
	if (!priv->base) {
		printk(KERN_ERR "%s: cannot remap memory!\n", DRV_NAME);
		startslot = slot + 1;
		rc = -EBUSY;
		goto err_out_reg;
	}

	mca_device_set_name(mdev, ibmlana_adapter_names[mdev->index]);
	mca_device_set_claim(mdev, 1);

	/* set methods */

	dev->open = ibmlana_open;
	dev->stop = ibmlana_close;
	dev->hard_start_xmit = ibmlana_tx;
	dev->set_multicast_list = ibmlana_set_multicast_list;
	dev->flags |= IFF_MULTICAST;

	/* copy out MAC address */

	for (z = 0; z < sizeof(dev->dev_addr); z++)
		dev->dev_addr[z] = inb(dev->base_addr + MACADDRPROM + z);

	/* print config */

	printk(KERN_INFO "%s: IRQ %d, I/O %#lx, memory %#lx-%#lx, "
	       "MAC address %s.\n",
	       dev->name, priv->realirq, dev->base_addr,
	       dev->mem_start, dev->mem_end - 1,
	       print_mac(mac, dev->dev_addr));
	printk(KERN_INFO "%s: %s medium\n", dev->name, MediaNames[priv->medium]);

	/* reset board */

	ResetBoard(dev);

	/* next probe will start at next slot */

	startslot = slot + 1;

	rc = register_netdev(dev);
	if (rc)
		goto err_out_claimed;

	dev_set_drvdata(kdev, dev);
	return 0;

err_out_claimed:
	mca_device_set_claim(mdev, 0);
	iounmap(priv->base);
err_out_reg:
	release_region(iobase, IBM_LANA_IORANGE);
err_out:
	free_netdev(dev);
	return rc;
}