/*
 * Probe for CMD640x -- vlb
 */
static int __init probe_for_cmd640_vlb(void)
{
	u8 b;

	__get_cmd640_reg = get_cmd640_reg_vlb;
	__put_cmd640_reg = put_cmd640_reg_vlb;
	cmd640_key = 0x178;
	b = get_cmd640_reg(CFR);
	if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) {
		cmd640_key = 0x78;
		b = get_cmd640_reg(CFR);
		if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h))
			return 0;
	}
	return 1; /* success */
}
static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
	unsigned int index = 0, cycle_time;
	u8 b;

	switch (pio) {
	case 6: /* set fast-devsel off */
	case 7: /* set fast-devsel on */
		b = get_cmd640_reg(CNTRL) & ~0x27;
		if (pio & 1)
			b |= 0x27;
		put_cmd640_reg(CNTRL, b);
		printk("%s: %sabled cmd640 fast host timing (devsel)\n",
			drive->name, (pio & 1) ? "en" : "dis");
		return;
	case 8: /* set prefetch off */
	case 9: /* set prefetch on */
		set_prefetch_mode(drive, index, pio & 1);
		printk("%s: %sabled cmd640 prefetch\n",
			drive->name, (pio & 1) ? "en" : "dis");
		return;
	}

	cycle_time = ide_pio_cycle_time(drive, pio);
	cmd640_set_mode(drive, index, pio, cycle_time);

	printk("%s: selected cmd640 PIO mode%d (%dns)",
		drive->name, pio, cycle_time);

	display_clocks(index);
}
static int __init match_pci_cmd640_device(void)
{
	const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
	unsigned int i;
	for (i = 0; i < 4; i++) {
		if (get_cmd640_reg(i) != ven_dev[i])
			return 0;
	}
#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT
	if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) {
		printk("ide: cmd640 on PCI disabled by BIOS\n");
		return 0;
	}
#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */
	return 1; /* success */
}
static int cmd640_test_irq(ide_hwif_t *hwif)
{
	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
	u8  irq_mask		= hwif->channel ? ARTTIM23_IDE23INTR :
						  CFR_IDE01INTR;
	u8  irq_stat		= get_cmd640_reg(irq_reg);

	return (irq_stat & irq_mask) ? 1 : 0;
}
Exemple #5
0
	/*
	 * Tell everyone what we did to their system
	 */
	printk("; serialized, secondary port %s\n", second_port_toggled ? "toggled" : "untouched");
	return 1;
}

#if 0  /* not used anywhere */
int cmd640_off(void) {
	static int a = 0;
	byte b;

	if (bus_type == none || a == 1)
		return 0;
	a = 1;
	b = get_cmd640_reg(CNTRL);	
	b &= ~CNTRL_ENA_2ND;
	put_cmd640_reg(CNTRL, b);
	return 1;
}
/*
 * Dump out all cmd640 registers.  May be called from ide.c
 */
static void cmd640_dump_regs(void)
{
	unsigned int reg = cmd640_vlb ? 0x50 : 0x00;

	/* Dump current state of chip registers */
	printk("ide: cmd640 internal register dump:");
	for (; reg <= 0x59; reg++) {
		if (!(reg & 0x0f))
			printk("\n%04x:", reg);
		printk(" %02x", get_cmd640_reg(reg));
	}
	printk("\n");
}
Exemple #7
0
static void set_readahead_mode(int mode, int if_num, int dr_num)
{
	static int masks[2][2] = 
		{ 
			{CNTRL_DIS_RA0, CNTRL_DIS_RA1}, 
			{DIS_RA2, 	DIS_RA3}
		};

	int port = (if_num == 0) ? CNTRL : ARTTIM23;
	int mask = masks[if_num][dr_num];
	byte b;

	b = get_cmd640_reg(port);
	if (mode)
		b &= ~mask;	/* Enable readahead for specific drive */
	else
		b |= mask;	/* Disable readahead for specific drive */
	put_cmd640_reg(port, b);
}		
Exemple #8
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;
}
/*
 * 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);
}
/*
 * Check whether prefetch is on for a drive,
 * and initialize the unmask flags for safe operation.
 */
static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
{
	u8 b = get_cmd640_reg(prefetch_regs[index]);

	__set_prefetch_mode(drive, (b & prefetch_masks[index]) ? 0 : 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);
}