Esempio n. 1
0
/*
 * 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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
}