/* * 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); }
int ide_probe_for_cmd640x(void) { int second_port_toggled = 0; byte b; if (probe_for_cmd640_pci1()) { bus_type = pci1; } else if (probe_for_cmd640_pci2()) { bus_type = pci2; } else if (cmd640_vlb && probe_for_cmd640_vlb()) { /* May be remove cmd640_vlb at all, and probe in any case */ bus_type = vlb; } else { return 0; } ide_hwifs[0].serialized = 1; /* ensure this *always* gets set */ ide_hwifs[1].serialized = 1; /* ensure this *always* gets set */ #if 0 /* Dump initial state of chip registers */ for (b = 0; b != 0xff; b++) { printk(" %2x%c", get_cmd640_reg(b), ((b&0xf) == 0xf) ? '\n' : ','); } #endif /* * Undocumented magic. (There is no 0x5b port in specs) */ put_cmd640_reg(0x5b, 0xbd); if (get_cmd640_reg(0x5b) != 0xbd) { printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n"); return 0; } put_cmd640_reg(0x5b, 0); /* * Documented magic. */ cmd640_chip_version = get_cmd640_reg(CFR) & CFR_DEVREV; if (cmd640_chip_version == 0) { printk ("ide: wrong CMD640 version -- 0\n"); return 0; } /* * Setup the most conservative timings for all drives, */ put_cmd640_reg(ARTTIM0, 0xc0); put_cmd640_reg(ARTTIM1, 0xc0); put_cmd640_reg(ARTTIM23, 0xcc); /* 0xc0? */ /* * Set the maximum allowed bus speed (it is safest until we * find how to detect bus speed) * Normally PCI bus runs at 33MHz, but often works overclocked to 40 */ bus_speed = (bus_type == vlb) ? 50 : 40; /* * Setup Control Register */ b = get_cmd640_reg(CNTRL); if (!secondary_port_responding()) { b ^= CNTRL_ENA_2ND; /* toggle the bit */ second_port_toggled = 1; } /* * Disable readahead for drives at primary interface */ b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1); put_cmd640_reg(CNTRL, b); /* * Note that we assume that the first interface is at 0x1f0, * and that the second interface, if enabled, is at 0x170. */ ide_hwifs[0].chipset = ide_cmd640; ide_hwifs[0].tuneproc = &cmd640_tune_drive; if (ide_hwifs[0].drives[0].autotune == 0) ide_hwifs[0].drives[0].autotune = 1; if (ide_hwifs[0].drives[1].autotune == 0) ide_hwifs[0].drives[1].autotune = 1; /* * Initialize 2nd IDE port, if required */ if (secondary_port_responding()) { ide_hwifs[1].chipset = ide_cmd640; ide_hwifs[1].tuneproc = &cmd640_tune_drive; if (ide_hwifs[1].drives[0].autotune == 0) ide_hwifs[1].drives[0].autotune = 1; if (ide_hwifs[1].drives[1].autotune == 0) ide_hwifs[1].drives[1].autotune = 1; /* disable read-ahead for drives 2 & 3 */ put_cmd640_reg(ARTTIM23, (DIS_RA2 | DIS_RA3)); if (second_port_toggled) { /* reset PIO timings for drives 2 & 3 */ put_cmd640_reg(DRWTIM23, 0); } #if 0 /* reset the secondary interface */ cmd640_reset_controller(1); #endif } printk("ide: buggy CMD640%c interface on ", 'A' - 1 + cmd640_chip_version); switch (bus_type) { case vlb : printk("vlb (0x%x)", cmd640_key); break; case pci1: printk("pci (0x%x)", cmd640_key); break; case pci2: printk("pci (access method 2) (0x%x)", cmd640_key); break; } #if 0 /* reset PIO timings for drives 1 & 2 */ put_cmd640_reg(CMDTIM, 0); #endif /* 0 */ /* * Tell everyone what we did to their system */ printk("; serialized, secondary port %s\n", second_port_toggled ? "toggled" : "untouched"); return 1; }
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); }