linux/drivers/ide/pci/opti621.c
Bartlomiej Zolnierkiewicz ced3ec8aa7 ide: prefix messages from IDE PCI host drivers by driver name
Prefix messages from IDE PCI host drivers by driver name instead of marketed
chipset name (it is still possible to exactly identify the particular chipset
basing on driver messages).

As a bonus this provides nice code savings for some drivers:

   text    data     bss     dec     hex filename
   3826     112       8    3946     f6a drivers/ide/pci/amd74xx.o.before
   2786     112       8    2906     b5a drivers/ide/pci/amd74xx.o.after
    764     108       0     872     368 drivers/ide/pci/cs5520.o.before
    680     108       0     788     314 drivers/ide/pci/cs5520.o.after
   1680     112       4    1796     704 drivers/ide/pci/generic.o.before
   1155     112       4    1271     4f7 drivers/ide/pci/generic.o.after
   7128     792       0    7920    1ef0 drivers/ide/pci/hpt366.o.before
   6984     792       0    7776    1e60 drivers/ide/pci/hpt366.o.after
   2800     148       0    2948     b84 drivers/ide/pci/pdc202xx_new.o.before
   2523     148       0    2671     a6f drivers/ide/pci/pdc202xx_new.o.after
   2831     148       0    2979     ba3 drivers/ide/pci/pdc202xx_old.o.before
   2683     148       0    2831     b0f drivers/ide/pci/pdc202xx_old.o.after
   3776     112       4    3892     f34 drivers/ide/pci/piix.o.before
   2804     112       4    2920     b68 drivers/ide/pci/piix.o.after
   4693     116       0    4809    12c9 drivers/ide/pci/siimage.o.before
   4600     116       0    4716    126c drivers/ide/pci/siimage.o.after

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-07-24 22:53:32 +02:00

247 lines
7.4 KiB
C

/*
* Copyright (C) 1996-1998 Linus Torvalds & authors (see below)
*/
/*
* Authors:
* Jaromir Koutek <miri@punknet.cz>,
* Jan Harkes <jaharkes@cwi.nl>,
* Mark Lord <mlord@pobox.com>
* Some parts of code are from ali14xx.c and from rz1000.c.
*
* OPTi is trademark of OPTi, Octek is trademark of Octek.
*
* I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps
* and disassembled/traced setupvic.exe (DOS program).
* It increases kernel code about 2 kB.
* I don't have this card no more, but I hope I can get some in case
* of needed development.
* My card is Octek PIDE 1.01 (on card) or OPTiViC (program).
* It has a place for a secondary connector in circuit, but nothing
* is there. Also BIOS says no address for
* secondary controller (see bellow in ide_init_opti621).
* I've only tested this on my system, which only has one disk.
* It's Western Digital WDAC2850, with PIO mode 3. The PCI bus
* is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random
* lockups). I tried the OCTEK double speed CD-ROM and
* it does not work! But I can't boot DOS also, so it's probably
* hardware fault. I have connected Conner 80MB, the Seagate 850MB (no
* problems) and Seagate 1GB (as slave, WD as master). My experiences
* with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes
* it slows to about 100kB/s! I don't know why and I have
* not this drive now, so I can't try it again.
* I write this driver because I lost the paper ("manual") with
* 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).
* 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
* I have 4 Megs/s before, but I don't know why (maybe changes
* in hdparm test).
* After release of 0.1, I got some successful reports, so it might work.
*
* The main problem with OPTi is that some timings for master
* and slave must be the same. For example, if you have master
* PIO 3 and slave PIO 0, driver have to set some timings of
* master for PIO 0. Second problem is that opti621_set_pio_mode
* got only one drive to set, but have to set both drives.
* 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.
* There is a 25/33MHz switch in configuration
* register, but driver is written for use at any frequency.
*
* Version 0.1, Nov 8, 1996
* by Jaromir Koutek, for 2.1.8.
* Initial version of driver.
*
* Version 0.2
* Number 0.2 skipped.
*
* Version 0.3, Nov 29, 1997
* by Mark Lord (probably), for 2.1.68
* Updates for use with new IDE block driver.
*
* Version 0.4, Dec 14, 1997
* by Jan Harkes
* Fixed some errors and cleaned the code.
*
* Version 0.5, Jan 2, 1998
* by Jaromir Koutek
* Updates for use with (again) new IDE block driver.
* Update of documentation.
*
* Version 0.6, Jan 2, 1999
* by Jaromir Koutek
* Reversed to version 0.3 of the driver, because
* 0.5 doesn't work.
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/io.h>
#define DRV_NAME "opti621"
#define READ_REG 0 /* index of Read cycle timing register */
#define WRITE_REG 1 /* index of Write cycle timing register */
#define CNTRL_REG 3 /* index of Control register */
#define STRAP_REG 5 /* index of Strap register */
#define MISC_REG 6 /* index of Miscellaneous register */
static int reg_base;
static DEFINE_SPINLOCK(opti621_lock);
/* Write value to register reg, base of register
* is at reg_base (0x1f0 primary, 0x170 secondary,
* if not changed by PCI configuration).
* This is from setupvic.exe program.
*/
static void write_reg(u8 value, int reg)
{
inw(reg_base + 1);
inw(reg_base + 1);
outb(3, reg_base + 2);
outb(value, reg_base + reg);
outb(0x83, reg_base + 2);
}
/* Read value from register reg, base of register
* is at reg_base (0x1f0 primary, 0x170 secondary,
* if not changed by PCI configuration).
* This is from setupvic.exe program.
*/
static u8 read_reg(int reg)
{
u8 ret = 0;
inw(reg_base + 1);
inw(reg_base + 1);
outb(3, reg_base + 2);
ret = inb(reg_base + reg);
outb(0x83, reg_base + 2);
return ret;
}
static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = drive->hwif;
ide_drive_t *pair = ide_get_paired_drive(drive);
unsigned long flags;
u8 tim, misc, addr_pio = pio, clk;
/* DRDY is default 2 (by OPTi Databook) */
static const u8 addr_timings[2][5] = {
{ 0x20, 0x10, 0x00, 0x00, 0x00 }, /* 33 MHz */
{ 0x10, 0x10, 0x00, 0x00, 0x00 }, /* 25 MHz */
};
static const u8 data_rec_timings[2][5] = {
{ 0x5b, 0x45, 0x32, 0x21, 0x20 }, /* 33 MHz */
{ 0x48, 0x34, 0x21, 0x10, 0x10 } /* 25 MHz */
};
drive->drive_data = XFER_PIO_0 + pio;
if (pair->present) {
if (pair->drive_data && pair->drive_data < drive->drive_data)
addr_pio = pair->drive_data - XFER_PIO_0;
}
spin_lock_irqsave(&opti621_lock, flags);
reg_base = hwif->io_ports.data_addr;
/* allow Register-B */
outb(0xc0, reg_base + CNTRL_REG);
/* hmm, setupvic.exe does this ;-) */
outb(0xff, reg_base + 5);
/* if reads 0xff, adapter not exist? */
(void)inb(reg_base + CNTRL_REG);
/* if reads 0xc0, no interface exist? */
read_reg(CNTRL_REG);
/* check CLK speed */
clk = read_reg(STRAP_REG) & 1;
printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33);
tim = data_rec_timings[clk][pio];
misc = addr_timings[clk][addr_pio];
/* select Index-0/1 for Register-A/B */
write_reg(drive->select.b.unit, MISC_REG);
/* set read cycle timings */
write_reg(tim, READ_REG);
/* set write cycle timings */
write_reg(tim, WRITE_REG);
/* use Register-A for drive 0 */
/* use Register-B for drive 1 */
write_reg(0x85, CNTRL_REG);
/* set address setup, DRDY timings, */
/* and read prefetch for both drives */
write_reg(misc, MISC_REG);
spin_unlock_irqrestore(&opti621_lock, flags);
}
static const struct ide_port_ops opti621_port_ops = {
.set_pio_mode = opti621_set_pio_mode,
};
static const struct ide_port_info opti621_chipset __devinitdata = {
.name = DRV_NAME,
.enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
.port_ops = &opti621_port_ops,
.host_flags = IDE_HFLAG_NO_DMA,
.pio_mask = ATA_PIO4,
};
static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
return ide_pci_init_one(dev, &opti621_chipset, NULL);
}
static const struct pci_device_id opti621_pci_tbl[] = {
{ PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 },
{ PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
static struct pci_driver driver = {
.name = "Opti621_IDE",
.id_table = opti621_pci_tbl,
.probe = opti621_init_one,
.remove = ide_pci_remove,
};
static int __init opti621_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
static void __exit opti621_ide_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(opti621_ide_init);
module_exit(opti621_ide_exit);
MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord");
MODULE_DESCRIPTION("PCI driver module for Opti621 IDE");
MODULE_LICENSE("GPL");