patch-2.1.68 linux/drivers/block/opti621.c

Next file: linux/drivers/block/pdc4030.c
Previous file: linux/drivers/block/ide.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.67/linux/drivers/block/opti621.c linux/drivers/block/opti621.c
@@ -1,7 +1,7 @@
 /*
- *  linux/drivers/block/opti621.c       Version 0.1  Oct 26, 1996
+ *  linux/drivers/block/opti621.c       Version 0.3  Nov 29, 1997
  *
- *  Copyright (C) 1996  Linus Torvalds & author (see below)
+ *  Copyright (C) 1996-1998  Linus Torvalds & author (see below)
  */
 
 /*
@@ -33,8 +33,8 @@
  * PIO 3 and slave PIO 0, driver have to set some timings of
  * master for PIO 0. Second problem is that opti621_tune_drive
  * got only one drive to set, but have to set both drives.
- * This is solved in opti621_compute_pios. If you don't set
- * the second drive, opti621_compute_pios use ide_get_best_pio_mode
+ * This is solved in compute_pios. If you don't set
+ * the second drive, compute_pios use ide_get_best_pio_mode
  * for autoselect mode (you can change it to PIO 0, if you want).
  * If you then set the second drive to another PIO, the old value
  * (automatically selected) will be overrided by yours.
@@ -48,7 +48,7 @@
  * settings of jumpers on the card and I have to boot Linux with
  * Loadlin except LILO, cause I have to run the setupvic.exe program
  * already or I get disk errors (my test: rpm -Vf
- * /usr/X11R6/bin/XF86_SVGA - or any big file). 
+ * /usr/X11R6/bin/XF86_SVGA - or any big file).
  * Some numbers from hdparm -t /dev/hda:
  * Timing buffer-cache reads:   32 MB in  3.02 seconds =10.60 MB/sec
  * Timing buffered disk reads:  16 MB in  5.52 seconds = 2.90 MB/sec
@@ -84,7 +84,7 @@
  *  address: 25 ns, data: 25 ns, recovery: 50 ns;
  * on 20MHz PCI bus (pulse 50 ns):
  *  address: 50 ns, data: 50 ns, recovery: 100 ns.
- */ 
+ */
 
 /* #define READ_PREFETCH 0 */
 /* Uncommnent for disable read prefetch.
@@ -103,58 +103,35 @@
 #define MISC_REG 6	/* index of Miscellaneous register */
 #define CNTRL_REG 3	/* index of Control register */
 int reg_base;
-int opti621_primary_base, opti621_secondary_base;
 
 #define PIO_NOT_EXIST 254
 #define PIO_DONT_KNOW 255
-int opti621_drive_pio_modes[4];
+
 /* there are stored pio numbers from other calls of opti621_tune_drive */
 
-void opti621_compute_pios(ide_hwif_t *drv, int second_contr, int slave_drive, byte pio)
-/* Store values into opti621_drive_pio_modes:
+static void compute_pios(ide_drive_t *drive, byte pio)
+/* Store values into drive->timing_data
  *	second_contr - 0 for primary controller, 1 for secondary
  *	slave_drive - 0 -> pio is for master, 1 -> pio is for slave
- *	pio - PIO mode for selected drive (for other we don't know)	
- */	 
+ *	pio - PIO mode for selected drive (for other we don't know)
+ */
 {
-	ide_drive_t *p1, *p2, *drive;
-	int i;
-	
-	i = 2*second_contr;
-	p1 = &drv->drives[0];
-	p2 = &drv->drives[1];
-	drive = &drv->drives[slave_drive]; 
-	pio = ide_get_best_pio_mode(drive, pio, OPTI621_MAX_PIO, NULL);
-	opti621_drive_pio_modes[i+slave_drive]=pio;
-
-	if (p1->present) {
-		if (opti621_drive_pio_modes[i]==PIO_DONT_KNOW)
-			opti621_drive_pio_modes[i]=ide_get_best_pio_mode(p1,
-				255, OPTI621_MAX_PIO, NULL);
-		/* we don't know the selected PIO mode, so we have to autoselect */
-	} else
-		opti621_drive_pio_modes[i]=PIO_NOT_EXIST;
-	if (p2->present) {
-		if (opti621_drive_pio_modes[i+1]==PIO_DONT_KNOW)
-			opti621_drive_pio_modes[i+1]=ide_get_best_pio_mode(p2,
-				255, OPTI621_MAX_PIO, NULL);
-		/* we don't know the selected PIO mode, so we have to autoselect */
-	} else
-		opti621_drive_pio_modes[i+1]=PIO_NOT_EXIST;
-	/* in opti621_drive_pio_modes[i] and [i+1] are valid PIO modes (or PIO_NOT_EXIST,
-		if drive is not connected), we can continue */
+	int d;
+	ide_hwif_t *hwif = HWIF(drive);
+
+	drive->timing_data = ide_get_best_pio_mode(drive, pio, OPTI621_MAX_PIO, NULL);
+	for (d = 0; d < 2; ++d) {
+		drive = &hwif->drives[d];
+		if (drive->present) {
+			if (drive->timing_data == PIO_DONT_KNOW)
+				drive->timing_data = ide_get_best_pio_mode(drive, 255, OPTI621_MAX_PIO, NULL);
 #ifdef OPTI621_DEBUG
-	printk("%s: (master): ", p1->name);
-	if (p1->present)
-		printk("PIO mode %d\n", opti621_drive_pio_modes[i]);
-	else
-		printk("not present\n");
-	printk("%s: (slave): ", p2->name);
-	if (p2->present)
-		printk("PIO mode %d\n", opti621_drive_pio_modes[i+1]);
-	else
-		printk("not present\n");
+			printk("%s: Selected PIO mode %d\n", drive->name, drive->timing_data);
 #endif
+		} else {
+			drive->timing_data = PIO_NOT_EXIST;
+		}
+	}
 }
 
 int cmpt_clk(int time, int bus_speed)
@@ -169,7 +146,7 @@
 	return ((time*bus_speed+999)/1000);
 }
 
-void write_reg(byte value, int reg)
+static void write_reg(byte value, int reg)
 /* Write value to register reg, base of register
  * is at reg_base (0x1f0 primary, 0x170 secondary,
  * if not changed by PCI configuration).
@@ -180,12 +157,12 @@
 	inw(reg_base+1);
 	outb(3, reg_base+2);
 	outb(value, reg_base+reg);
-	outb(0x83, reg_base+2);	
+	outb(0x83, reg_base+2);
 }
 
-byte read_reg(int reg)
+static byte read_reg(int reg)
 /* Read value from register reg, base of register
- * is at reg_base (0x1f0 primary, 0x170 secondary, 
+ * is at reg_base (0x1f0 primary, 0x170 secondary,
  * if not changed by PCI configuration).
  * This is from setupvic.exe program.
  */
@@ -195,7 +172,7 @@
 	inw(reg_base+1);
 	outb(3, reg_base+2);
 	ret=inb(reg_base+reg);
-	outb(0x83, reg_base+2);	
+	outb(0x83, reg_base+2);
 	return ret;
 }
 
@@ -205,9 +182,9 @@
 	int	recovery_time;	/* Recovery time (clocks) */
 } pio_clocks_t;
 
-void compute_clocks(int pio, pio_clocks_t *clks)
+static void compute_clocks(int pio, pio_clocks_t *clks)
 {
-        if (pio!=PIO_NOT_EXIST) {
+        if (pio != PIO_NOT_EXIST) {
         	int adr_setup, data_pls, bus_speed;
         	bus_speed = ide_system_bus_speed();
  	       	adr_setup = ide_pio_timings[pio].setup_time;
@@ -230,108 +207,80 @@
 	}
 }
 
-static void opti621_tune_drive (ide_drive_t *drive, byte pio)
 /* Main tune procedure, hooked by tuneproc. */
+static void opti621_tune_drive (ide_drive_t *drive, byte pio)
 {
-	/* primary and secondary drives share some (but not same) registers,
-	so we have to program both drives */
+	/* primary and secondary drives share some registers,
+	 * so we have to program both drives
+	 */
 	unsigned long flags;
 	byte pio1, pio2;
-	int second_contr, slave_drive;
 	pio_clocks_t first, second;
 	int ax, drdy;
 	byte cycle1, cycle2, misc;
-		
-	second_contr=HWIF(drive)->index;
-	if ((second_contr!=0) && (second_contr!=1))
-		return; /* invalid controller number */
-	if (((second_contr==0) && (opti621_primary_base==0)) ||
-		((second_contr==1) && (opti621_secondary_base==0)))
-		return; /* controller is unaccessible/not exist */
-	slave_drive = drive->select.b.unit;
-	/* set opti621_drive_pio_modes[] */
-	opti621_compute_pios(HWIF(drive), second_contr, slave_drive, pio);
-	
-     	reg_base = second_contr ? opti621_primary_base : opti621_secondary_base;
-
- 	pio1 = opti621_drive_pio_modes[second_contr*2];
- 	pio2 = opti621_drive_pio_modes[second_contr*2+1];
- 	
+	ide_hwif_t *hwif = HWIF(drive);
+
+	/* set drive->timing_data for both drives */
+	compute_pios(drive, pio);
+ 	pio1 = hwif->drives[0].timing_data;
+ 	pio2 = hwif->drives[1].timing_data;
+
 	compute_clocks(pio1, &first);
 	compute_clocks(pio2, &second);
-	
-	ax = (first.address_time<second.address_time) ?
-		(second.address_time) : (first.address_time); /* in ax is max(a1,a2) */
+
+	/* ax = max(a1,a2) */
+	ax = (first.address_time < second.address_time) ? second.address_time : first.address_time;
+
 	drdy = 2; /* DRDY is default 2 (by OPTi Databook) */
 
 	cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2);
 	cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2);
 	misc = READ_PREFETCH | ((ax-1)<<4) | ((drdy-2)<<1);
-	
+
 #ifdef OPTI621_DEBUG
 	printk("%s: master: address: %d, data: %d, recovery: %d, drdy: %d [clk]\n",
-		HWIF(drive)->name, ax, first.data_time, first.recovery_time, drdy);
+		hwif->name, ax, first.data_time, first.recovery_time, drdy);
 	printk("%s: slave:  address: %d, data: %d, recovery: %d, drdy: %d [clk]\n",
-		HWIF(drive)->name, ax, second.data_time, second.recovery_time, drdy);
+		hwif->name, ax, second.data_time, second.recovery_time, drdy);
 #endif
 
 	save_flags(flags);
 	cli();
-	
+
+     	reg_base = hwif->io_ports[IDE_DATA_OFFSET];
 	outb(0xc0, reg_base+CNTRL_REG);	/* allow Register-B */
 	outb(0xff, reg_base+5);		/* hmm, setupvic.exe does this ;-) */
 	inb(reg_base+CNTRL_REG); 	/* if reads 0xff, adapter not exist? */
 	read_reg(CNTRL_REG);		/* if reads 0xc0, no interface exist? */
 	read_reg(5);			/* read version, probably 0 */
-	
-	/* programming primary drive - 0 or 2 */
-	write_reg(0, MISC_REG);		/* select Index-0 for Register-A */
+
+	/* program primary drive */
+	write_reg(0,      MISC_REG);	/* select Index-0 for Register-A */
 	write_reg(cycle1, READ_REG);	/* set read cycle timings */
 	write_reg(cycle1, WRITE_REG);	/* set write cycle timings */
 
-	/* programming secondary drive - 1 or 3 */
-	write_reg(1, MISC_REG); /* select Index-1 for Register-B */
-	write_reg(cycle2, READ_REG); /* set read cycle timings */
-	write_reg(cycle2, WRITE_REG); /* set write cycle timings */
-	
-	write_reg(0x85, CNTRL_REG); /* use Register-A for drive 0 (or 2) and
-		Register-B for drive 1 (or 3) */ 
-		
- 	write_reg(misc, MISC_REG); /* set address setup, DRDY timings
- 		and read prefetch for both drives */
-		
+	/* program secondary drive */
+	write_reg(1,      MISC_REG);	/* select Index-1 for Register-B */
+	write_reg(cycle2, READ_REG);	/* set read cycle timings */
+	write_reg(cycle2, WRITE_REG);	/* set write cycle timings */
+
+	write_reg(0x85, CNTRL_REG);	/* use Register-A for drive 0 */
+					/* use Register-B for drive 1 */
+
+ 	write_reg(misc, MISC_REG);	/* set address setup, DRDY timings,   */
+ 					/*  and read prefetch for both drives */
+
 	restore_flags(flags);
 }
 
-void ide_init_opti621 (byte bus, byte fn)
-/* Init controller. Called on kernel boot. */
+/*
+ * ide_init_opti621() is Called from idedma.c once for each hwif found at boot.
+ */
+void ide_init_opti621 (byte bus, byte fn, ide_hwif_t *hwifs)
 {
-	int rc, i;
-	unsigned char sreg;
-	unsigned short reg;
-	unsigned int dreg;
-	unsigned char revision;
-	for (i=0; i<4; i++)
-		opti621_drive_pio_modes[i] = PIO_DONT_KNOW;
-	printk("ide: OPTi 82C621 on PCI bus %d function %d\n", bus, fn);
-	if ((rc = pcibios_read_config_byte (bus, fn, 0x08, &sreg)))
-		goto quit;
-	revision = sreg;
-	if ((rc = pcibios_read_config_dword (bus, fn, 0x10, &dreg)))
-		goto quit;
-	opti621_primary_base = ((dreg==0) || (dreg>0xffff)) ? 0 : dreg-1;
-	if ((rc = pcibios_read_config_dword (bus, fn, 0x18, &dreg)))
-		goto quit;
-	opti621_secondary_base = ((dreg==0) || (dreg>0xffff)) ? 0 : dreg-1;
-	printk("ide: revision %d, primary: 0x%04x, secondary: 0x%04x\n",
-		revision, opti621_primary_base, opti621_secondary_base);
-	if ((rc = pcibios_read_config_word (bus, fn, PCI_COMMAND, &reg)))
-		goto quit;
-	if (!(reg & 1)) {
-		printk("ide: ports are not enabled (BIOS)\n");
-	} else {
-		ide_hwifs[0].tuneproc = &opti621_tune_drive;
-		ide_hwifs[1].tuneproc = &opti621_tune_drive;
-  	}
-  quit: if (rc) printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
+	if (hwif->io_ports[IDE_DATA_OFFSET]) {
+		hwif->drives[0].timing_data = PIO_DONT_KNOW;
+		hwif->drives[1].timing_data = PIO_DONT_KNOW;
+		hwif->tuneproc = &opti621_tune_drive;
+	}
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov