示例#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);
}
示例#2
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);
}