static void getaddrs(struct mca_device *mdev, int *base, int *memlen, int *iobase, int *irq, ibmlana_medium *medium) { u_char pos0, pos1; pos0 = mca_device_read_stored_pos(mdev, 2); pos1 = mca_device_read_stored_pos(mdev, 3); *base = 0xc0000 + ((pos1 & 0xf0) << 9); *memlen = (pos1 & 0x01) ? 0x8000 : 0x4000; *iobase = (pos0 & 0xe0) << 7; switch (pos0 & 0x06) { case 0: *irq = 5; break; case 2: *irq = 15; break; case 4: *irq = 10; break; case 6: *irq = 11; break; } *medium = (pos0 & 0x18) >> 3; }
/** * mca_read_stored_pos - read POS register from boot data * @slot: slot number to read from * @reg: register to read from * * Fetch a POS value that was stored at boot time by the kernel * when it scanned the MCA space. The register value is returned. * Missing or invalid registers report 0. */ unsigned char mca_read_stored_pos(int slot, int reg) { struct mca_device *mca_dev = mca_find_device_by_slot(slot); if(!mca_dev) return 0; return mca_device_read_stored_pos(mca_dev, reg); }
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; }