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; }
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; }
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; }
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; }
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; }
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; }
/* 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; }
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; }
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; }
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; }
/* 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; }
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; }
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 ) {
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; }
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; }