/* * Probe for a cmd640 chipset, and initialize it if found. */ static int __init cmd640x_init(void) { int second_port_cmd640 = 0, rc; const char *bus_type, *port2; u8 b, cfr; hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; if (cmd640_vlb && probe_for_cmd640_vlb()) { bus_type = "VLB"; } else { cmd640_vlb = 0; /* Find out what kind of PCI probing is supported otherwise Justin Gibbs will sulk.. */ if (pci_conf1() && probe_for_cmd640_pci1()) bus_type = "PCI (type1)"; else if (pci_conf2() && probe_for_cmd640_pci2()) bus_type = "PCI (type2)"; else return 0; } /* * Undocumented magic (there is no 0x5b reg in specs) */ put_cmd640_reg(0x5b, 0xbd); if (get_cmd640_reg(0x5b) != 0xbd) { printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n"); return 0; } put_cmd640_reg(0x5b, 0); #ifdef CMD640_DUMP_REGS cmd640_dump_regs(); #endif /* * Documented magic begins here */ cfr = get_cmd640_reg(CFR); cmd640_chip_version = cfr & CFR_DEVREV; if (cmd640_chip_version == 0) { printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version); return 0; } rc = cmd640x_init_one(0x1f0, 0x3f6); if (rc) return rc; rc = cmd640x_init_one(0x170, 0x376); if (rc) { release_region(0x3f6, 1); release_region(0x1f0, 8); return rc; } memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); hw[0].irq = 14; hw[0].chipset = ide_cmd640; ide_std_init_ports(&hw[1], 0x170, 0x376); hw[1].irq = 15; hw[1].chipset = ide_cmd640; printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); /* * Initialize data for primary port */ hws[0] = &hw[0]; /* * Ensure compatibility by always using the slowest timings * for access to the drive's command register block, * and reset the prefetch burstsize to default (512 bytes). * * Maybe we need a way to NOT do these on *some* systems? */ put_cmd640_reg(CMDTIM, 0); put_cmd640_reg(BRST, 0x40); b = get_cmd640_reg(CNTRL); /* * Try to enable the secondary interface, if not already enabled */ if (secondary_port_responding()) { if ((b & CNTRL_ENA_2ND)) { second_port_cmd640 = 1; port2 = "okay"; } else if (cmd640_vlb) { second_port_cmd640 = 1; port2 = "alive"; } else port2 = "not cmd640"; } else { put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ if (secondary_port_responding()) { second_port_cmd640 = 1; port2 = "enabled"; } else { put_cmd640_reg(CNTRL, b); /* restore original setting */ port2 = "not responding"; } } /* * Initialize data for secondary cmd640 port, if enabled */ if (second_port_cmd640) hws[1] = &hw[1]; printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n", second_port_cmd640 ? "" : "not ", port2); #ifdef CMD640_DUMP_REGS cmd640_dump_regs(); #endif return ide_host_add(&cmd640_port_info, hws, NULL); }
static int __init cmd640x_init(void) { int second_port_cmd640 = 0, rc; const char *bus_type, *port2; u8 b, cfr; struct ide_hw hw[2], *hws[2]; if (cmd640_vlb && probe_for_cmd640_vlb()) { bus_type = "VLB"; } else { cmd640_vlb = 0; /* */ if (pci_conf1() && probe_for_cmd640_pci1()) bus_type = "PCI (type1)"; else if (pci_conf2() && probe_for_cmd640_pci2()) bus_type = "PCI (type2)"; else return 0; } /* */ put_cmd640_reg(0x5b, 0xbd); if (get_cmd640_reg(0x5b) != 0xbd) { printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n"); return 0; } put_cmd640_reg(0x5b, 0); #ifdef CMD640_DUMP_REGS cmd640_dump_regs(); #endif /* */ cfr = get_cmd640_reg(CFR); cmd640_chip_version = cfr & CFR_DEVREV; if (cmd640_chip_version == 0) { printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version); return 0; } rc = cmd640x_init_one(0x1f0, 0x3f6); if (rc) return rc; rc = cmd640x_init_one(0x170, 0x376); if (rc) { release_region(0x3f6, 1); release_region(0x1f0, 8); return rc; } memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); hw[0].irq = 14; ide_std_init_ports(&hw[1], 0x170, 0x376); hw[1].irq = 15; printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); /* */ hws[0] = &hw[0]; /* */ put_cmd640_reg(CMDTIM, 0); put_cmd640_reg(BRST, 0x40); b = get_cmd640_reg(CNTRL); /* */ if (secondary_port_responding()) { if ((b & CNTRL_ENA_2ND)) { second_port_cmd640 = 1; port2 = "okay"; } else if (cmd640_vlb) { second_port_cmd640 = 1; port2 = "alive"; } else port2 = "not cmd640"; } else { put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* */ if (secondary_port_responding()) { second_port_cmd640 = 1; port2 = "enabled"; } else { put_cmd640_reg(CNTRL, b); /* */ port2 = "not responding"; } } /* */ if (second_port_cmd640) hws[1] = &hw[1]; printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n", second_port_cmd640 ? "" : "not ", port2); #ifdef CMD640_DUMP_REGS cmd640_dump_regs(); #endif return ide_host_add(&cmd640_port_info, hws, second_port_cmd640 ? 2 : 1, NULL); }