All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-03 11:16 ` PATCH: Add support for IT8212 IDE controllers Elmar Hinz
@ 2004-08-03 10:50   ` Alan Cox
  2004-08-03 12:18     ` Elmar Hinz
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Cox @ 2004-08-03 10:50 UTC (permalink / raw)
  To: Elmar Hinz; +Cc: Linux Kernel Mailing List

On Maw, 2004-08-03 at 12:16, Elmar Hinz wrote:
> Alan Cox wrote:
> > There is a messy scsi faking vendor driver for this card but this instead
> > is a standard Linux IDE layer driver.
> > 
> 
> I try to answer to this post. As I newly subscribed to this list, I 
> probably won't catch the original thread.

Not your fault - I missed out an include file update when I posted it -
PCI_DEVICE_ID_ITE_8212 is 0x8212..


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
       [not found] <2obsK-5Ni-13@gated-at.bofh.it>
@ 2004-08-03 11:16 ` Elmar Hinz
  2004-08-03 10:50   ` Alan Cox
  2004-08-04 14:03 ` Elmar Hinz
  1 sibling, 1 reply; 13+ messages in thread
From: Elmar Hinz @ 2004-08-03 11:16 UTC (permalink / raw)
  To: linux-kernel

Alan Cox wrote:
> There is a messy scsi faking vendor driver for this card but this instead
> is a standard Linux IDE layer driver.
> 

I try to answer to this post. As I newly subscribed to this list, I 
probably won't catch the original thread.

After application of this patch I get the following error during 
compilation. This are my first steps with kernel patching. Probably the 
fault is on my side.

Regards Elmar



   CC      drivers/ide/pci/it8212.o
drivers/ide/pci/it8212.c:643: error: `PCI_DEVICE_ID_ITE_8212' undeclared 
here (not in a function)
drivers/ide/pci/it8212.c:643: error: Initialisierungselement ist nicht 
konstant
drivers/ide/pci/it8212.c:643: error: (near initialization for 
`it8212_pci_tbl[0].device')
drivers/ide/pci/it8212.c:643: error: Initialisierungselement ist nicht 
konstant
drivers/ide/pci/it8212.c:643: error: (near initialization for 
`it8212_pci_tbl[0]')
drivers/ide/pci/it8212.c:644: error: Initialisierungselement ist nicht 
konstant
drivers/ide/pci/it8212.c:644: error: (near initialization for 
`it8212_pci_tbl[1]')
make[4]: *** [drivers/ide/pci/it8212.o] Fehler 1
make[3]: *** [drivers/ide/pci] Fehler 2
make[2]: *** [drivers/ide] Fehler 2
make[1]: *** [drivers] Fehler 2
make[1]: Verlasse Verzeichnis »/usr/src/linux-2.6.8-rc2«
make: *** [stamp-build] Fehler 2



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-03 10:50   ` Alan Cox
@ 2004-08-03 12:18     ` Elmar Hinz
  2004-08-03 20:42       ` Elmar Hinz
  0 siblings, 1 reply; 13+ messages in thread
From: Elmar Hinz @ 2004-08-03 12:18 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alan Cox

> 
> 
> Not your fault - I missed out an include file update when I posted it -
> PCI_DEVICE_ID_ITE_8212 is 0x8212..
> 
> 

Oops. I only understand "trainstation". I guess you will put the fixed 
patch on the list. Do you? :-)

In drivers/ide/pci/ some other drivers have a *.h file. Maybe you mean that?

Then I discover on http://lkml.org/lkml/2004/8/1/121 a double linebreak, 
wich causes an error. It is not there in the newsgroup. Strange.



#define DECLARE_ITE_DEV(name_str)			\

	{						\
		.name		= name_str,		\
		.init_chipset	= init_chipset_it8212,	\
		.init_hwif	= init_hwif_it8212,	\
		.channels	= 2,			\
		.autodma	= AUTODMA,		\
		.bootable	= ON_BOARD,		\
	}


Regards

Elmar





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-03 12:18     ` Elmar Hinz
@ 2004-08-03 20:42       ` Elmar Hinz
  0 siblings, 0 replies; 13+ messages in thread
From: Elmar Hinz @ 2004-08-03 20:42 UTC (permalink / raw)
  To: linux-kernel

>> Not your fault - I missed out an include file update when I posted it -
>> PCI_DEVICE_ID_ITE_8212 is 0x8212..
>>

This seems to mean:

put this

#define PCI_DEVICE_ID_ITE_8212             0x8212

into that

/usr/src/kernel-source-2.x.x/include/linux/pci_ids.h

Regards

Elmar


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
       [not found] <2obsK-5Ni-13@gated-at.bofh.it>
  2004-08-03 11:16 ` PATCH: Add support for IT8212 IDE controllers Elmar Hinz
@ 2004-08-04 14:03 ` Elmar Hinz
  2004-08-05 10:47   ` Alan Cox
  2004-08-14 19:32   ` Alan Cox
  1 sibling, 2 replies; 13+ messages in thread
From: Elmar Hinz @ 2004-08-04 14:03 UTC (permalink / raw)
  To: Alan Cox, linux-kernel

Hello,

here some personel observations. Maybe they are result of little 
experience of mine. Maybe they are of use for others.

I use rev11 of it/ite8212 Dual Channel ATA RAID controller. On each 
master there is a 80GB harddisk.

When I set in the bios RAID 1 there comes an message similar
INVALID GEOMETRY: 0 PHYSICAL HEADS?
and booting stops.

When I set NORMAL, I get IRQ-timeouts for both disks. (IRQ 10)

but booting continous and I can use the disks.

hdparm => 15.70 MB/sec

Elmar









^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-04 14:03 ` Elmar Hinz
@ 2004-08-05 10:47   ` Alan Cox
  2004-08-06 21:58     ` Elmar Hinz
  2004-08-14 19:32   ` Alan Cox
  1 sibling, 1 reply; 13+ messages in thread
From: Alan Cox @ 2004-08-05 10:47 UTC (permalink / raw)
  To: Elmar Hinz; +Cc: Alan Cox, linux-kernel

On Wed, Aug 04, 2004 at 04:03:43PM +0200, Elmar Hinz wrote:
> When I set in the bios RAID 1 there comes an message similar
> INVALID GEOMETRY: 0 PHYSICAL HEADS?
> and booting stops.

At which point

> but booting continous and I can use the disks.
> hdparm => 15.70 MB/sec

A bit slow.. thanks


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-05 10:47   ` Alan Cox
@ 2004-08-06 21:58     ` Elmar Hinz
  0 siblings, 0 replies; 13+ messages in thread
From: Elmar Hinz @ 2004-08-06 21:58 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel

Alan Cox wrote:
> On Wed, Aug 04, 2004 at 04:03:43PM +0200, Elmar Hinz wrote:
> 
>>When I set in the bios RAID 1 there comes an message similar
>>INVALID GEOMETRY: 0 PHYSICAL HEADS?
>>and booting stops.
> 
> 
> At which point
> 
> 
>>but booting continous and I can use the disks.
>>hdparm => 15.70 MB/sec
> 
> 
> A bit slow.. thanks
> 
> 

I am sorry. I can't test the card in the RAID mode anymore, because it
is in use meanwhile with NORMAL mode an a software raid. Maybe the
output of dmesg in NORMAL mode is usefull for you.


Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx
IT8212: IDE controller at PCI slot 0000:00:09.0
PCI: Found IRQ 10 for device 0000:00:09.0
PCI: Sharing IRQ 10 with 0000:00:01.2

(Changing the slots IRQ by bios alters both devices 0000:00:01.2 and 
0000:00:09.0, so they seem to belong both to the card/disks)

IT8212: chipset revision 17
IT8212: 100% native mode on irq 10
     ide2: BM-DMA at 0xb000-0xb007, BIOS settings: hde:DMA, hdf:pio
it8212: controller in smart mode.
it8212: BIOS seleted a 66MHz clock.
     ide3: BM-DMA at 0xb008-0xb00f, BIOS settings: hdg:DMA, hdh:pio
it8212: BIOS seleted a 66MHz clock.
hde: WDC WD800JB-00FMA0, ATA DISK drive
ide2 at 0xd400-0xd407,0xd002 on irq 10
hdg: WDC WD800JB-00FMA0, ATA DISK drive
ide3 at 0xb800-0xb807,0xb402 on irq 10
hdc: ATAPI CDROM, ATAPI CD/DVD-ROM drive
ide1 at 0x170-0x177,0x376 on irq 15
hde: max request size: 128KiB
hde: recal_intr: status=0x51 { DriveReady SeekComplete Error }
hde: recal_intr: error=0x04 { DriveStatusError }
hde: 156301488 sectors (80026 MB) w/8192KiB Cache, CHS=65535/16/63, UDMA(33)
hde: irq timeout: status=0xd0 { Busy }

  /dev/ide/host2/bus0/target0/lun0: p1 < p5 p6 p7 p8 >
hdg: max request size: 128KiB
hdg: recal_intr: status=0x51 { DriveReady SeekComplete Error }
hdg: recal_intr: error=0x04 { DriveStatusError }
hdg: 156301488 sectors (80026 MB) w/8192KiB Cache, CHS=65535/16/63, UDMA(33)
hdg: irq timeout: status=0xd0 { Busy }

  /dev/ide/host2/bus1/target0/lun0: p1 < p5 p6 p7 p8 >

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-04 14:03 ` Elmar Hinz
  2004-08-05 10:47   ` Alan Cox
@ 2004-08-14 19:32   ` Alan Cox
  1 sibling, 0 replies; 13+ messages in thread
From: Alan Cox @ 2004-08-14 19:32 UTC (permalink / raw)
  To: Elmar Hinz; +Cc: Alan Cox, Linux Kernel Mailing List

On Mer, 2004-08-04 at 15:03, Elmar Hinz wrote:
> When I set in the bios RAID 1 there comes an message similar
> INVALID GEOMETRY: 0 PHYSICAL HEADS?
> and booting stops.

Should be fixed now. I'm running a bios raid1 and it seems to be 
doing the right thing. Turns out we had a locking bug on that error
path and the identify block from the raid volumes was wrong

I've added some quirk code to fix up the fields in the identify 
data to indicate LBA28/48 is supported, report that the UDMA data
provided is valid (so we turn DMA on and get cable CRCs).

I've also added code to the it8212 driver to filter the 48bit flush
cache command (seems to kill my card), only queue 128K per I/O (LBA48
full sized I/O's also seem to kill my card) and to skip the 0x27 (native
size) query the firmware doesn't seem to know.

Alan


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-01 23:05   ` Alan Cox
@ 2004-08-06  0:45     ` Ian Hastie
  0 siblings, 0 replies; 13+ messages in thread
From: Ian Hastie @ 2004-08-06  0:45 UTC (permalink / raw)
  To: Alan Cox; +Cc: Linux Kernel Mailing List, linux-ide

On Monday 02 Aug 2004 00:05, Alan Cox wrote:
> Ok try this

OK, tried it now.  Sorry it took so long to get around to it.

It gets the ATA clock setting right, but that's the only obvious change.  
Everything else in the boot log seems the same.

The UDMA rate is still detected wrongly, but this is because the PCI reg 0x40 
contains the value 0xa000 which should mean 40 wire cables.  I am using 
rounded canbles, but I can't say if this would cause a misdetection or not.  
The ITE driver seems to suggest that cable detect can only be used if the 
chip is in "Firmware" mode.  I thought I saw a more definite reference to 
this, but I can't seem to find it now.  It's certainly true that I have not 
seen any data corruption on the connected drives even when running at hat 
should be UDMA133.

One other small point is that SMART doesn't work through this driver.  
smartctl -A says there is a checksum error and then says SMART is not active.

IT8212: IDE controller at PCI slot 0000:00:0c.0
ACPI: PCI interrupt 0000:00:0c.0[A] -> GSI 17 (level, low) -> IRQ 17
IT8212: chipset revision 17
IT8212: 100% native mode on irq 17
ide2: BM-DMA at 0xec00-0xec07, BIOS settings: hde:pio, hdf:pio
it8212: controller in smart mode.
it8212: BIOS seleted a 66MHz clock.
ide3: BM-DMA at 0xec08-0xec0f, BIOS settings: hdg:pio, hdh:pio
it8212: BIOS seleted a 66MHz clock.
hde: Maxtor 6Y120P0, ATA DISK drive
ide2 at 0xb000-0xb007,0xa802 on irq 17
hde: max request size: 128KiB
hde: recal_intr: status=0x51 { DriveReady SeekComplete Error }
hde: recal_intr: error=0x04 { DriveStatusError }
hde: 240121728 sectors (122942 MB) w/7936KiB Cache, CHS=65535/16/63, UDMA(33)
/dev/ide/host2/bus0/target0/lun0: p1 p2
hdg: Maxtor 6Y120P0, ATA DISK drive
ide3 at 0xa400-0xa407,0xa002 on irq 17
hdg: max request size: 128KiB
hdg: recal_intr: status=0x51 { DriveReady SeekComplete Error }
hdg: recal_intr: error=0x04 { DriveStatusError }
hdg: 240121728 sectors (122942 MB) w/7936KiB Cache, CHS=65535/16/63, UDMA(33)
/dev/ide/host2/bus1/target0/lun0: p1 p2

-- 
Ian.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-01 19:22 ` Ian Hastie
  2004-08-01 20:10   ` Alan Cox
@ 2004-08-01 23:05   ` Alan Cox
  2004-08-06  0:45     ` Ian Hastie
  1 sibling, 1 reply; 13+ messages in thread
From: Alan Cox @ 2004-08-01 23:05 UTC (permalink / raw)
  To: Ian Hastie; +Cc: Linux Kernel Mailing List, linux-ide, Alan Cox

[-- Attachment #1: Type: text/plain, Size: 14 bytes --]

Ok try this



[-- Attachment #2: it8212.c --]
[-- Type: text/x-csrc, Size: 20544 bytes --]

/*
 * linux/drivers/ide/pci/it8212.c		Version 0.02	August 2004
 *
 * Copyright (C) 2004		Red Hat <alan@redhat.com>
 *
 *  May be copied or modified under the terms of the GNU General Public License
 *
 *  Documentation available from
 * 	http://www.ite.com.tw/pc/IT8212F_V04.pdf
 *
 *  The ITE8212 isn't exactly a standard IDE controller. It has two
 *  modes. In pass through mode then it is an IDE controller. In its smart
 *  mode its actually quite a capable hardware raid controller disguised
 *  as an IDE controller.
 *
 *  Errata:
 *	Rev 0x10 also requires master/slave use the same UDMA timing and
 *	cannot do ATAPI DMA, while the other revisions can do ATAPI UDMA
 *	but not MWDMA.
 *
 *  This has a few impacts on the driver
 *  - In pass through mode we do all the work you would expect
 *  - In smart mode the clocking set up is done by the controller generally
 *  - There are a few extra vendor commands that actually talk to the 
 *    controller but only work PIO with no IRQ.
 *
 *  Vendor areas of the identify block in smart mode are used for the
 *  timing and policy set up. Each HDD in raid mode also has a serial
 *  block on the disk. The hardware extra commands are get/set chip status,
 *  rebuild, get rebuild status.
 *
 *  In Linux the driver supports pass through mode as if the device was
 *  just another IDE controller. If the smart mode is running then
 *  volumes are managed by the controller firmware and each IDE "disk"
 *  is a raid volume. Even more cute - the controller can do automated
 *  hotplug and rebuild.
 *
 *  The pass through controller itself is a little demented. It has a
 *  flaw that it has a single set of PIO/MWDMA timings per channel so
 *  non UDMA devices restrict each others performance. It also has a 
 *  single clock source per channel so mixed UDMA100/133 performance
 *  isn't perfect and we have to pick a clock. Thankfully none of this
 *  matters in smart mode. ATAPI DMA is not supported. 
 *
 *  TODO
 *	-	Rev 0x10 in pass through mode needs UDMA clock whacking
 *		to work around h/w issues
 *	-	Is rev 0x10 out anywhere - test it if so
 *	-	More testing
 *	-	Find an Innovision 8401D r R board somewhere to test that
 *	-	See if we can kick the cheapo board into smart mode
 *		ourselves 8)
 *	-	ATAPI UDMA is ok but not MWDMA it seems
 *	-	RAID configuration ioctls
 */
 
#include <linux/config.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>

#include <asm/io.h>

struct it8212_dev
{
	int	smart:1,		/* Are we in smart raid mode */
		timing10:1;		/* Rev 0x10 */
	u8	clock_mode;		/* 0, ATA_50 or ATA_66 */
	u8	want[2][2];		/* Mode/Pri log for master slave */
	/* We need these for switching the clock when DMA goes on/off 
	   The high byte is the 66Mhz timing */
	u16	pio[2];			/* Cached PIO values */
	u16	mwdma[2];		/* Cached MWDMA values */
	u16	udma[2];		/* Cached UDMA values (per drive) */
};

#define ATA_66		0
#define ATA_50		1
#define ATA_ANY		2

#define UDMA_OFF	0
#define MWDMA_OFF	0


/**
 *	it8212_program	-	program the PIO/MWDMA registers
 *	@drive: drive to tune
 *
 *	Program the PIO/MWDMA timing for this channel according to the
 *	current clock.
 */
 
static void it8212_program(ide_drive_t *drive, u16 timing)
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
	int channel = hwif->channel;
	u8 conf;
	
	/* Program PIO/MWDMA timing bits */
	if(itdev->clock_mode == ATA_66)
		conf = timing >> 8;
	else	
		conf = timing & 0xFF;
	pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
}

/**
 *	it8212_program	-	program the PIO/MWDMA registers
 *	@drive: drive to tune
 *
 *	Program the UDMA timing for this drive according to the
 *	current clock.
 */
 
static void it8212_program_udma(ide_drive_t *drive, u16 timing)
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
	int channel = hwif->channel;
	int unit = drive->select.b.unit;
	u8 conf;
	
	/* Program UDMA timing bits */
	if(itdev->clock_mode == ATA_66)
		conf = timing >> 8;
	else
		conf = timing & 0xFF;
	pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf);
}


/**
 *	it8212_clock_strategy
 *	@hwif: hardware interface
 *
 *	Select between the 50 and 66Mhz base clocks to get the best
 *	results for this interface.
 */
 
static void it8212_clock_strategy(ide_drive_t *drive)
{
	ide_hwif_t *hwif = HWIF(drive);
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);

	u8 unit = drive->select.b.unit;
	ide_drive_t *pair = &hwif->drives[1-unit];

	int clock, altclock;
	u8 v;
	int sel = 0;

	if(itdev->want[0][0] > itdev->want[1][0])
	{
		clock = itdev->want[0][1];
		altclock = itdev->want[1][1];
	}
	else
	{
		clock = itdev->want[1][1];
		altclock = itdev->want[0][1];
	}

	/* Master doesn't care does the secondary ? */
	if(clock == ATA_ANY)
		clock = altclock;
		
	/* Nobody cares - keep the same clock */
	if(clock == ATA_ANY)
		return;
	/* No change */
	if(clock == itdev->clock_mode)
		return;
		
	/* Load this into the controller ? */
	if(clock == ATA_66)
		itdev->clock_mode = ATA_66;
	else
	{
		itdev->clock_mode = ATA_50;
		sel = 1;
	}
	pci_read_config_byte(hwif->pci_dev, 0x50, &v);
	v &= ~(1 << (1 + hwif->channel));
	v |= sel << (1 + hwif->channel);
	pci_write_config_byte(hwif->pci_dev, 0x50, v);
	printk(KERN_INFO "it8212: selected %dMHz clock.\n", itdev->clock_mode == ATA_66?66:50);
	
	/*
	 *	Reprogram the UDMA/PIO of the pair drive for the switch
	 *	MWDMA will be dealt with by the dma switcher
	 */
	if(pair && itdev->udma[1-unit] != UDMA_OFF)
	{
		it8212_program_udma(pair, itdev->udma[1-unit]);
		it8212_program(pair, itdev->pio[1-unit]);
	}
	/*
	 *	Reprogram the UDMA/PIO of our drive for the switch.
	 *	MWDMA will be dealt with by the dma switcher
	 */
	if(itdev->udma[unit] != UDMA_OFF)
	{
		it8212_program_udma(drive, itdev->udma[unit]);
		it8212_program(drive, itdev->pio[unit]);
	}
}

/**
 *	it8212_ratemask	-	Compute available modes
 *	@drive: IDE drive
 *
 *	Compute the available speeds for the devices on the interface. This
 *	is all modes to ATA133 clipped by drive cable setup.
 */
 
static byte it8212_ratemask (ide_drive_t *drive)
{
	u8 mode	= 4;
	if (!eighty_ninty_three(drive))
		mode = min(mode, (u8)1);
	return mode;
}

/**
 *	it8212_tuneproc	-	tune a drive 
 *	@drive: drive to tune
 *	@mode_wanted: the target operating mode
 *
 *	Load the timing settings for this device mode into the
 *	controller. By the time we are called the mode has been 
 *	modified as neccessary to handle the absence of seperate
 *	master/slave timers for MWDMA/PIO.
 *
 *	This code is only used in pass through mode.
 */
 
static void it8212_tuneproc (ide_drive_t *drive, byte mode_wanted)
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
	int unit = drive->select.b.unit;
	
	/* Spec says 89 ref driver uses 88 */
	static u16 pio[]	= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
	static u8 pio_want[]    = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
	
	/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
	itdev->want[unit][1] = pio_want[mode_wanted];
	itdev->want[unit][0] = 1;	/* PIO is lowest priority */
	itdev->pio[unit] = pio[mode_wanted];
	it8212_clock_strategy(drive);
	it8212_program(drive, itdev->pio[unit]);
}

/**
 *	it8212_tune_mwdma	-	tune a channel for MWDMA
 *	@drive: drive to set up
 *	@mode_wanted: the target operating mode
 *
 *	Load the timing settings for this device mode into the
 *	controller when doing MWDMA in pass through mode. The caller
 *	must manage the whole lack of per device MWDMA/PIO timings and
 *	the shared MWDMA/PIO timing register.
 */
 
static void it8212_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct it8212_dev *itdev = (void *)ide_get_hwifdata(hwif);
	int unit = drive->select.b.unit;
	int channel = hwif->channel;
	u8 conf;
	
	static u16 dma[]	= { 0x8866, 0x3222, 0x3121 };
	static u8 mwdma_want[]	= { ATA_ANY, ATA_66, ATA_ANY };
	
	itdev->want[unit][1] = mwdma_want[mode_wanted];
	itdev->want[unit][0] = 2;	/* MWDMA is low priority */
	itdev->mwdma[unit] = dma[mode_wanted];
	itdev->udma[unit] = UDMA_OFF;
	
	/* UDMA bits off */
	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
	conf |= 1 << (3 + 2 * channel + unit);
	pci_write_config_byte(hwif->pci_dev, 0x50, conf);

	it8212_clock_strategy(drive);
	/* FIXME: do we need to program this ? */
	it8212_program(drive, itdev->mwdma[unit]);
}

/**
 *	it8212_tune_udma	-	tune a channel for UDMA
 *	@drive: drive to set up
 *	@mode_wanted: the target operating mode
 *
 *	Load the timing settings for this device mode into the
 *	controller when doing UDMA modes in pass through.
 */
 
static void it8212_tune_udma (ide_drive_t *drive, byte mode_wanted)
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
	int unit = drive->select.b.unit;
	int channel = hwif->channel;
	u8 conf;

	static u16 udma[]	= { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
	static u8 udma_want[]	= { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
	
	itdev->want[unit][1] = udma_want[mode_wanted];
	itdev->want[unit][0] = 3;	/* UDMA is high priority */
	itdev->mwdma[unit] = MWDMA_OFF;
	itdev->udma[unit] = udma[mode_wanted];
	if(mode_wanted >= 5)
		itdev->udma[unit] |= 0x8080;	/* UDMA 5/6 select on */
		
	/* UDMA on */
	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
	conf &= ~ (1 << (3 + 2 * channel + unit));
	pci_write_config_byte(hwif->pci_dev, 0x50, conf);

	it8212_clock_strategy(drive);
	it8212_program_udma(drive, itdev->udma[unit]);
	
}

/**
 *	config_it8212_chipset_for_pio	-	set drive timings
 *	@drive: drive to tune
 *	@speed we want
 *
 *	Compute the best pio mode we can for a given device. We must
 *	pick a speed that does not cause problems with the other device
 *	on the cable.
 */
 
static void config_it8212_chipset_for_pio (ide_drive_t *drive, byte set_speed)
{
	u8 unit = drive->select.b.unit;
	ide_hwif_t *hwif = HWIF(drive);
	ide_drive_t *pair = &hwif->drives[1-unit];
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
	u8 speed = 0, set_pio	= ide_get_best_pio_mode(drive, 4, 5, NULL);
	u8 pair_pio;
	
	/* We have to deal with this mess in pairs */
	if(pair != NULL)
	{
		pair_pio = ide_get_best_pio_mode(pair, 4, 5, NULL);
		/* Trim PIO to the slowest of the master/slave */
		if(pair_pio < set_pio)
			set_pio = pair_pio;
	}
	if(!itdev->smart)
		it8212_tuneproc(drive, set_pio);
	speed = XFER_PIO_0 + set_pio;
	/* XXX - We trim to the lowest of the pair so the other drive
	   will always be fine at this point until we do hotplug passthru */
	   
	if (set_speed)
		(void) ide_config_drive_speed(drive, speed);
}

static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
{
	config_it8212_chipset_for_pio(drive, set_speed);
}

/**
 *	it8212_dma_read	-	DMA hook
 *	@drive: drive for DMA
 *
 *	The IT8212 has a single timing register for MWDMA and for PIO
 *	operations. As we flip back and forth we have to reload the
 *	clock.
 *
 *	FIXME: for 0x10 model we should reprogram UDMA here
 */
 
static int it8212_dma_begin(ide_drive_t *drive)
{
	ide_hwif_t *hwif = HWIF(drive);
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
	int unit = drive->select.b.unit;
	if(itdev->mwdma[unit] != MWDMA_OFF)
		it8212_program(drive, itdev->mwdma[unit]);
	return __ide_dma_begin(drive);
}

/**
 *	it8212_dma_write	-	DMA hook
 *	@drive: drive for DMA stop
 *
 *	The IT8212 has a single timing register for MWDMA and for PIO
 *	operations. As we flip back and forth we have to reload the
 *	clock.
 *
 *	FIXME: for 0x10 model we should reprogram UDMA here
 */
 
static int it8212_dma_end(ide_drive_t *drive)
{
	ide_hwif_t *hwif = HWIF(drive);
	int unit = drive->select.b.unit;
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
	int ret = __ide_dma_end(drive);
	if(itdev->mwdma[unit] != MWDMA_OFF)
		it8212_program(drive, itdev->pio[unit]);
	return ret;
}

	
/**
 *	it8212_tune_chipset	-	set controller timings
 *	@drive: Drive to set up
 *	@xferspeed: speed we want to achieve
 *
 *	Tune the ITE chipset for the desired mode. If we can't achieve
 *	the desired mode then tune for a lower one, but ultimately
 *	make the thing work.
 */
 
static int it8212_tune_chipset (ide_drive_t *drive, byte xferspeed)
{

	ide_hwif_t *hwif	= HWIF(drive);
	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
	u8 speed		= ide_rate_filter(it8212_ratemask(drive), xferspeed);
				    
	switch(speed) {
		case XFER_PIO_4:
		case XFER_PIO_3:
		case XFER_PIO_2:
		case XFER_PIO_1:
		case XFER_PIO_0:
			if(!itdev->smart)
				it8212_tuneproc(drive, (speed - XFER_PIO_0));
			break;
		/* MWDMA tuning is really hard because our MWDMA and PIO
		   timings are kept in the same place. We can switch in the 
		   host dma on/off callbacks */
		case XFER_MW_DMA_2:
		case XFER_MW_DMA_1:
		case XFER_MW_DMA_0:
			if(!itdev->smart)
				it8212_tune_mwdma(drive, (speed - XFER_MW_DMA_0));
			break;
		case XFER_UDMA_6:
		case XFER_UDMA_5:
		case XFER_UDMA_4:
		case XFER_UDMA_3:
		case XFER_UDMA_2:
		case XFER_UDMA_1:
		case XFER_UDMA_0:
			if(!itdev->smart)
				it8212_tune_udma(drive, (speed - XFER_UDMA_0));
			break;
		default:
			return 1;
	}
	/*
	 *	In smart mode the clocking is done by the host controller
	 * 	snooping the mode we picked. The rest of it is not our problem
	 */
	return (ide_config_drive_speed(drive, speed));
}

/**
 *	config_chipset_for_dma	-	configure for DMA
 *	@drive: drive to configure
 *
 *	Called by the IDE layer when it wants the timings set up.
 */
 
static int config_chipset_for_dma (ide_drive_t *drive)
{
	u8 speed	= ide_dma_speed(drive, it8212_ratemask(drive));

	config_chipset_for_pio(drive, !speed);

	if (!speed)
		return 0;

	if (ide_set_xfer_rate(drive, speed))
		return 0;

	if (!drive->init_speed)
		drive->init_speed = speed;

	return ide_dma_enable(drive);
}

/**
 *	it8212_configure_drive_for_dma	-	set up for DMA transfers
 *	@drive: drive we are going to set up
 *
 *	Set up the drive for DMA, tune the controller and drive as 
 *	required. If the drive isn't suitable for DMA or we hit
 *	other problems then we will drop down to PIO and set up
 *	PIO appropriately
 */
 
static int it8212_config_drive_for_dma (ide_drive_t *drive)
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct hd_driveid *id	= drive->id;

	if ((id->capability & 1) != 0 && drive->autodma) {
		/* Consult the list of known "bad" drives */
		if (__ide_dma_bad_drive(drive))
			goto fast_ata_pio;

		if ((id->field_valid & 4) && it8212_ratemask(drive)) {
			if (id->dma_ultra & hwif->ultra_mask) {
				/* Force if Capable UltraDMA */
				int dma = config_chipset_for_dma(drive);
				if ((id->field_valid & 2) && !dma)
					goto try_dma_modes;
			}
		} else if (id->field_valid & 2) {
try_dma_modes:
			if ((id->dma_mword & hwif->mwdma_mask) ||
			    (id->dma_1word & hwif->swdma_mask)) {
				/* Force if Capable regular DMA modes */
				if (!config_chipset_for_dma(drive))
					goto no_dma_set;
			}
		} else if (__ide_dma_good_drive(drive) &&
			   (id->eide_dma_time < 150)) {
			/* Consult the list of known "good" drives */
			if (!config_chipset_for_dma(drive))
				goto no_dma_set;
		} else {
			goto fast_ata_pio;
		}
		return hwif->ide_dma_on(drive);
	} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
no_dma_set:
		config_chipset_for_pio(drive, 1);
		return hwif->ide_dma_off_quietly(drive);
	}
	/* IORDY not supported */
	return 0;
}

/**
 *	init_chipset_it8212	-	set up an ITE device
 *	@dev: PCI device
 *	@name: device name
 *
 */

static unsigned int __devinit init_chipset_it8212(struct pci_dev *dev, const char *name)
{
	return 0;
}

/**
 *	ata66_it8212	-	check for 80 pin cable
 *	@hwif: interface to check
 *
 *	Check for the presence of an ATA66 capable cable on the
 *	interface. Note that the firmware writes bits 4-7 having done 
 *	the drive side sampling. This may impact hotplug.
 */

static unsigned int __devinit ata66_it8212(ide_hwif_t *hwif)
{
	u16 iocfg;
	
	pci_read_config_word(hwif->pci_dev, 0x40, &iocfg);
	if(iocfg & (1 << (4 + 2*hwif->channel)))
		return 1;
	return 0;
}

/**
 *	init_hwif_it8212	-	set up hwif structs
 *	@hwif: interface to set up
 *
 *	We do the basic set up of the interface structure. The IT8212
 *	requires several custom handlers so we override the default
 *	ide DMA handlers appropriately
 */

static void __devinit init_hwif_it8212(ide_hwif_t *hwif)
{
	struct it8212_dev *idev = kmalloc(sizeof(struct it8212_dev), GFP_KERNEL);
	u8 conf;
	
	if(idev == NULL)
	{
		printk(KERN_ERR "it8212: out of memory, falling back to legacy behaviour.\n");
		goto fallback;
	}
	memset(idev, 0, sizeof(*idev));
	ide_set_hwifdata(hwif, idev);
	
	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
	if(conf & 1)
	{
		if(hwif->channel == 0)
			printk(KERN_INFO "it8212: controller in smart mode.\n");
		idev->smart = 1;
	}
	else if(hwif->channel == 0)
		printk(KERN_INFO "it8212: controller in pass through mode.\n");
		
	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
	if (conf & (1 << (1 + hwif->channel)))
		idev->clock_mode = ATA_50;
	else
		idev->clock_mode = ATA_66;
		
	idev->want[0][1] = ATA_ANY;
	idev->want[1][1] = ATA_ANY;
		
	printk(KERN_INFO "it8212: BIOS seleted a %dMHz clock.\n", idev->clock_mode == ATA_66 ? 66:50);
	/*
	 *	Not in the docs but according to the reference driver
	 *	this is neccessary.
	 */
	pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
	if(conf == 0x10)
		idev->timing10 = 1;
#if 0	/* Needs more research */
	else
		hwif->atapi_dma = 1;
#endif

	if(idev->timing10 && !idev->smart)
	{
		printk(KERN_WARNING "it8212: DMA is not currently supported on revision 0x10 in pass through.\n");
		goto fallback;
	}
		
	hwif->speedproc = &it8212_tune_chipset;
	hwif->tuneproc	= &it8212_tuneproc;
	
	/* MWDMA/PIO clock switching for pass through mode */
	if(!idev->smart)
	{
		hwif->ide_dma_begin = &it8212_dma_begin;
		hwif->ide_dma_end = &it8212_dma_end;
	}

	if (!hwif->dma_base)
		goto fallback;

	hwif->ultra_mask = 0x7f;
	hwif->mwdma_mask = 0x07;
	hwif->swdma_mask = 0x07;

	hwif->ide_dma_check = &it8212_config_drive_for_dma;
	if (!(hwif->udma_four))
		hwif->udma_four = ata66_it8212(hwif);

	/*
	 *	The BIOS often doesn't set up DMA on this controller
	 *	so we always do it.
	 */

	hwif->autodma = 1;
	hwif->drives[0].autodma = hwif->autodma;
	hwif->drives[1].autodma = hwif->autodma;
	return;

fallback:
	hwif->autodma = 0;
	hwif->drives[0].autotune = 1;
	hwif->drives[1].autotune = 1;
	return;
}

#define DECLARE_ITE_DEV(name_str)			\
	{						\
		.name		= name_str,		\
		.init_chipset	= init_chipset_it8212,	\
		.init_hwif	= init_hwif_it8212,	\
		.channels	= 2,			\
		.autodma	= AUTODMA,		\
		.bootable	= ON_BOARD,		\
	}

static ide_pci_device_t it8212_chipsets[] __devinitdata = {
	/* 0 */ DECLARE_ITE_DEV("IT8212"),
};

/**
 *	it8212_init_one	-	pci layer discovery entry
 *	@dev: PCI device
 *	@id: ident table entry
 *
 *	Called by the PCI code when it finds an ITE8212 controller.
 *	We then use the IDE PCI generic helper to do most of the work.
 */
 
static int __devinit it8212_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
	ide_setup_pci_device(dev, &it8212_chipsets[id->driver_data]);
	return 0;
}

static struct pci_device_id it8212_pci_tbl[] = {
	{ PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
	{ 0, },
};

MODULE_DEVICE_TABLE(pci, it8212_pci_tbl);

static struct pci_driver driver = {
	.name		= "ITE8212 IDE",
	.id_table	= it8212_pci_tbl,
	.probe		= it8212_init_one,
};

static int it8212_ide_init(void)
{
	return ide_pci_register_driver(&driver);
}

module_init(it8212_ide_init);

MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("PCI driver module for the ITE 8212");
MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-08-01 19:22 ` Ian Hastie
@ 2004-08-01 20:10   ` Alan Cox
  2004-08-01 23:05   ` Alan Cox
  1 sibling, 0 replies; 13+ messages in thread
From: Alan Cox @ 2004-08-01 20:10 UTC (permalink / raw)
  To: Ian Hastie; +Cc: linux-kernel, linux-ide, Alan Cox

On Sun, Aug 01, 2004 at 08:22:28PM +0100, Ian Hastie wrote:
>         ide2: BM-DMA at 0xec00-0xec07, BIOS settings: hde:pio, hdf:pio
>     it8212: controller in RAID mode.
> 
> That doesn't.  I have no RAID sets defined in the IT8212 card BIOS.  BTW, the 

The controller runs in RAID mode on the "smart" cards even without raid 
definitions being used - its still doing the hardware assist.

>         ide3: BM-DMA at 0xec08-0xec0f, BIOS settings: hdg:pio, hdh:pio
>     hde: Maxtor 6Y120P0, ATA DISK drive
>     it8212: selected 50MHz clock.
> 
> Nor does this as it really should be using the 66MHz clock setting.

Currently it always picks 50MHz, thats a feature I'm still working on 
adding intelligence to

>     ide2 at 0xb000-0xb007,0xa802 on irq 17
>     hde: max request size: 128KiB
>     hde: recal_intr: status=0x51 { DriveReady SeekComplete Error }
>     hde: recal_intr: error=0x04 { DriveStatusError }
> 
> Any idea what could be causing this?  My hacked driver doesn't get this in 
> 2.6.7, but then it could be a 2.6.8 problem.

It was sent a command it didnt know.

The UDMA33 speed behaviour looks to me like cable detect got the wrong
answer. The reference driver doesn't actually do host side cable detect
so it may be that its in the docs but doesn't actually work or isnt wired
on the boards. Can you see what the ata66 function is doing ?


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: PATCH: Add support for IT8212 IDE controllers
  2004-07-31 23:22 Alan Cox
@ 2004-08-01 19:22 ` Ian Hastie
  2004-08-01 20:10   ` Alan Cox
  2004-08-01 23:05   ` Alan Cox
  0 siblings, 2 replies; 13+ messages in thread
From: Ian Hastie @ 2004-08-01 19:22 UTC (permalink / raw)
  To: linux-kernel, linux-ide; +Cc: Alan Cox

On Sunday 01 Aug 2004 00:22, Alan Cox wrote:
> There is a messy scsi faking vendor driver for this card but this instead
> is a standard Linux IDE layer driver.
> + *  Documentation available from
> + *     http://www.ite.com.tw/pc/IT8212F_V04.pdf

A newer version than the one I have.  Looks like there's at least one newer 
chip revision than the 0x11 that I have too.

Just need to add something like this to get it to compile.

--- linux-2.6.8-rc2/include/linux/pci_ids.h.it8212	2004-08-01 
18:44:08.000000000 +0100
+++ linux-2.6.8-rc2/include/linux/pci_ids.h	2004-08-01 19:14:44.000000000 
+0100
@@ -1634,6 +1634,7 @@
 #define PCI_VENDOR_ID_ITE		0x1283
 #define PCI_DEVICE_ID_ITE_IT8172G	0x8172
 #define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801
+#define	PCI_DEVICE_ID_ITE_8212		0x8212
 #define PCI_DEVICE_ID_ITE_8872		0x8872
 #define PCI_DEVICE_ID_ITE_IT8330G_0	0xe886
 
---

Some quick test results I just got.  My set up is a IT8212 PCI card running 
two UDMA133 discs in software RAID0.  I'd like to test the smart RAID some 
time, but that isn't really practical at the moment.

    IT8212: IDE controller at PCI slot 0000:00:0c.0
    ACPI: PCI interrupt 0000:00:0c.0[A] -> GSI 17 (level, low) -> IRQ 17
    IT8212: chipset revision 17
    IT8212: 100% native mode on irq 17

That makes sense.

        ide2: BM-DMA at 0xec00-0xec07, BIOS settings: hde:pio, hdf:pio
    it8212: controller in RAID mode.

That doesn't.  I have no RAID sets defined in the IT8212 card BIOS.  BTW, the 
BIOS is an old one and should be updated.  However when I tried the updater 
claimed success, but on reboot it hadn't changed.

        ide3: BM-DMA at 0xec08-0xec0f, BIOS settings: hdg:pio, hdh:pio
    hde: Maxtor 6Y120P0, ATA DISK drive
    it8212: selected 50MHz clock.

Nor does this as it really should be using the 66MHz clock setting.

    ide2 at 0xb000-0xb007,0xa802 on irq 17
    hde: max request size: 128KiB
    hde: recal_intr: status=0x51 { DriveReady SeekComplete Error }
    hde: recal_intr: error=0x04 { DriveStatusError }

Any idea what could be causing this?  My hacked driver doesn't get this in 
2.6.7, but then it could be a 2.6.8 problem.

    hde: 240121728 sectors (122942 MB) w/7936KiB Cache, CHS=65535/16/63, 
UDMA(33)

Oddly my driver reports UDMA(33) too, but that's probably bad coding as it is 
definitely running faster than that.

     /dev/ide/host2/bus0/target0/lun0: p1 p2
    hdg: Maxtor 6Y120P0, ATA DISK drive
    it8212: selected 50MHz clock.
    ide3 at 0xa400-0xa407,0xa002 on irq 17
    hdg: max request size: 128KiB
    hdg: recal_intr: status=0x51 { DriveReady SeekComplete Error }
    hdg: recal_intr: error=0x04 { DriveStatusError }
    hdg: 240121728 sectors (122942 MB) w/7936KiB Cache, CHS=65535/16/63, 
UDMA(33)
     /dev/ide/host2/bus1/target0/lun0: p1 p2

And the same speed problems again.

Now some speed tests with hdparm

# hdparm -Tt /dev/hd[eg] /dev/md[01]

/dev/hde:
 Timing buffer-cache reads:   3016 MB in  2.00 seconds = 1505.97 MB/sec
 Timing buffered disk reads:   86 MB in  3.02 seconds =  28.49 MB/sec

/dev/hdg:
 Timing buffer-cache reads:   3012 MB in  2.00 seconds = 1504.72 MB/sec
 Timing buffered disk reads:   86 MB in  3.02 seconds =  28.46 MB/sec

/dev/md0:
 Timing buffer-cache reads:   2928 MB in  2.00 seconds = 1462.03 MB/sec
 Timing buffered disk reads:  156 MB in  3.01 seconds =  51.90 MB/sec

/dev/md1:
 Timing buffer-cache reads:   2996 MB in  2.00 seconds = 1495.98 MB/sec
 Timing buffered disk reads:  156 MB in  3.01 seconds =  51.77 MB/sec

So I guess it actually is running at 33MHz!

Current results with my hack

# hdparm -Tt /dev/hd[eg] /dev/md[01]

/dev/hde:
 Timing buffer-cache reads:   2980 MB in  2.00 seconds = 1488.74 MB/sec
 Timing buffered disk reads:  172 MB in  3.02 seconds =  57.04 MB/sec

/dev/hdg:
 Timing buffer-cache reads:   2988 MB in  2.00 seconds = 1493.48 MB/sec
 Timing buffered disk reads:  170 MB in  3.03 seconds =  56.15 MB/sec

/dev/md0:
 Timing buffer-cache reads:   2964 MB in  2.00 seconds = 1480.74 MB/sec
 Timing buffered disk reads:  286 MB in  3.00 seconds =  95.25 MB/sec

/dev/md1:
 Timing buffer-cache reads:   2924 MB in  2.00 seconds = 1460.03 MB/sec
 Timing buffered disk reads:  290 MB in  3.01 seconds =  96.33 MB/sec

-- 
Ian.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* PATCH: Add support for IT8212 IDE controllers
@ 2004-07-31 23:22 Alan Cox
  2004-08-01 19:22 ` Ian Hastie
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Cox @ 2004-07-31 23:22 UTC (permalink / raw)
  To: linux-kernel, linux-ide

There is a messy scsi faking vendor driver for this card but this instead
is a standard Linux IDE layer driver.

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.8-rc2/drivers/ide/Kconfig linux-2.6.8-rc2/drivers/ide/Kconfig
--- linux.vanilla-2.6.8-rc2/drivers/ide/Kconfig	2004-07-27 19:22:42.000000000 +0100
+++ linux-2.6.8-rc2/drivers/ide/Kconfig	2004-07-31 17:15:35.000000000 +0100
@@ -621,6 +621,12 @@
 	  <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
 	  board at <http://www.mvista.com/partners/semiconductor/ite.html>.
 
+config BLK_DEV_IT8212
+	tristate "IT8212 IDE support (Experimental)"
+	help
+	  This driver adds support for the ITE 8212 IDE RAID controller in
+	  both RAID and pass-through mode. 
+
 config BLK_DEV_NS87415
 	tristate "NS87415 chipset support"
 	help
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.8-rc2/drivers/ide/pci/it8212.c linux-2.6.8-rc2/drivers/ide/pci/it8212.c
--- linux.vanilla-2.6.8-rc2/drivers/ide/pci/it8212.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.8-rc2/drivers/ide/pci/it8212.c	2004-07-31 22:18:14.000000000 +0100
@@ -0,0 +1,664 @@
+/*
+ * linux/drivers/ide/pci/it8212.c		Version 0.01	July 2004
+ *
+ * Copyright (C) 2004		Red Hat <alan@redhat.com>
+ *
+ *  May be copied or modified under the terms of the GNU General Public License
+ *
+ *  Documentation available from
+ * 	http://www.ite.com.tw/pc/IT8212F_V04.pdf
+ *
+ *  The ITE8212 isn't exactly a standard IDE controller. It has two
+ *  modes. In pass through mode then it is an IDE controller. In its smart
+ *  mode its actually quite a capable hardware raid controller disguised
+ *  as an IDE controller.
+ *
+ *  Errata:
+ *	Rev 0x10 also requires master/slave use the same UDMA timing and
+ *	cannot do ATAPI DMA, while the other revisions can do ATAPI UDMA
+ *	but not MWDMA.
+ *
+ *  This has a few impacts on the driver
+ *  - In pass through mode we do all the work you would expect
+ *  - In smart mode the clocking set up is done by the controller generally
+ *  - There are a few extra vendor commands that actually talk to the 
+ *    controller but only work PIO with no IRQ.
+ *
+ *  Vendor areas of the identify block in smart mode are used for the
+ *  timing and policy set up. Each HDD in raid mode also has a serial
+ *  block on the disk. The hardware extra commands are get/set chip status,
+ *  rebuild, get rebuild status.
+ *
+ *  In Linux the driver supports pass through mode as if the device was
+ *  just another IDE controller. If the smart mode is running then
+ *  volumes are managed by the controller firmware and each IDE "disk"
+ *  is a raid volume. Even more cute - the controller can do automated
+ *  hotplug and rebuild.
+ *
+ *  The pass through controller itself is a little demented. It has a
+ *  flaw that it has a single set of PIO/MWDMA timings per channel so
+ *  non UDMA devices restrict each others performance. It also has a 
+ *  single clock source per channel so mixed UDMA100/133 performance
+ *  isn't perfect and we have to pick a clock. Thankfully none of this
+ *  matters in smart mode. ATAPI DMA is not supported. 
+ *
+ *  TODO
+ *	-	Rev 0x10 in pass through mode needs UDMA clock whacking
+ *		to work around h/w issues
+ *	-	Is rev 0x10 out anywhere - test it if so
+ *	-	More testing
+ *	-	Find an Innovision 8401D or R board somewhere to test that
+ *	-	See if we can kick the cheapo board into smart mode
+ *		ourselves 8)
+ *	-	ATAPI UDMA is ok but not MWDMA it seems
+ *	-	Better clock strategy
+ *	-	RAID configuration ioctls
+ */
+ 
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+struct it8212_dev
+{
+	int	smart:1,		/* Are we in smart raid mode */
+		timing10:1;		/* Rev 0x10 */
+	u8	clock_mode;		/* 0, 50 or 66 */
+	u8	want[2][2];		/* Mode/Pri log for master slave */
+	
+	/* We need these for switching the clock when DMA goes on/off */
+	u8	pio[2];			/* Cached PIO values */
+	u8	mwdma[2];		/* Cached MWDMA values */
+};
+
+/**
+ *	it8212_clock_strategy
+ *	@hwif: hardware interface
+ *
+ *	Select between the 50 and 66Mhz base clocks to get the best
+ *	results for this interface. Right now our approach is stupidity
+ *	first until we have the driver stable
+ */
+ 
+static void it8212_clock_strategy(ide_drive_t *drive)
+{
+	u8 v;
+	int sel = 0;
+	ide_hwif_t *hwif = HWIF(drive);
+	int clock;
+	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
+	/* FIXME: Just to simplify we don't switch clocks once set */
+	if(itdev->clock_mode == 0)
+	{
+		if(itdev->want[0][0] > itdev->want[1][0])
+			clock = itdev->want[0][1];
+		else
+			clock = itdev->want[1][1];
+		/* Load this into the controller ? */
+		if(clock == 66)
+			itdev->clock_mode = 66;
+		else
+		{
+			itdev->clock_mode = 50;
+			sel = 1;
+		}
+		pci_read_config_byte(hwif->pci_dev, 0x50, &v);
+		v &= ~(1 << (1 + hwif->channel));
+		v |= sel << (1 + hwif->channel);
+		pci_write_config_byte(hwif->pci_dev, 0x50, v);
+		
+		printk(KERN_INFO "it8212: selected %dMHz clock.\n", itdev->clock_mode);
+	}
+}
+
+/**
+ *	it8212_ratemask	-	Compute available modes
+ *	@drive: IDE drive
+ *
+ *	Compute the available speeds for the devices on the interface. This
+ *	is all modes to ATA133 clipped by drive cable setup.
+ */
+ 
+static byte it8212_ratemask (ide_drive_t *drive)
+{
+	u8 mode	= 4;
+	if (!eighty_ninty_three(drive))
+		mode = min(mode, (u8)1);
+	return mode;
+}
+
+/**
+ *	it8212_tuneproc	-	tune a drive 
+ *	@drive: drive to tune
+ *	@mode_wanted: the target operating mode
+ *
+ *	Load the timing settings for this device mode into the
+ *	controller. By the time we are called the mode has been 
+ *	modified as neccessary to handle the absence of seperate
+ *	master/slave timers for MWDMA/PIO.
+ *
+ *	This code is only used in pass through mode.
+ */
+ 
+static void it8212_tuneproc (ide_drive_t *drive, byte mode_wanted)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
+	int unit = drive->select.b.unit;
+	int channel = hwif->channel;
+	u8 conf;
+	
+				/* Spec says 89 ref driver uses 88 */
+	static u8 pio_50[]	= { 0x88, 0x82, 0x81, 0x32, 0x21 };
+	static u8 pio_66[]   	= { 0xAA, 0xA3, 0xA1, 0x33, 0x31 };
+	
+	static u8 pio_want[]	= { 66, 66, 66, 66, 0 };
+	
+	/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
+	itdev->want[unit][0] = pio_want[mode_wanted];
+	itdev->want[unit][1] = 1;	/* PIO is lowest priority */
+	
+	it8212_clock_strategy(drive);
+	
+	/* Program PIO/MWDMA timing bits */
+	pci_read_config_byte(hwif->pci_dev, 0x54 + 4 * channel, &conf);
+	if(itdev->clock_mode == 66)
+		conf = pio_66[mode_wanted];
+	else	
+		conf = pio_50[mode_wanted];
+	pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
+	itdev->pio[unit] = conf	;
+}
+
+/**
+ *	it8212_tune_mwdma	-	tune a channel for MWDMA
+ *	@drive: drive to set up
+ *	@mode_wanted: the target operating mode
+ *
+ *	Load the timing settings for this device mode into the
+ *	controller when doing MWDMA in pass through mode. The caller
+ *	must manage the whole lack of per device MWDMA/PIO timings and
+ *	the shared MWDMA/PIO timing register.
+ *
+ *	FIXME: before we can enable MWDMA we need to cache PIO/MWDMA
+ *	timings and reload them on ide_dma_on/ide_dma_off_* because they
+ *	occupy the same register.
+ */
+ 
+static void it8212_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct it8212_dev *itdev = (void *)ide_get_hwifdata(hwif);
+	int unit = drive->select.b.unit;
+	int channel = hwif->channel;
+	u8 conf;
+	
+	static u8 dma_50[]	= { 0x66, 0x22, 0x21 };
+	static u8 dma_66[]	= { 0x88, 0x32, 0x31 };
+	
+	static u8 mwdma_want[]	= { 0, 66, 0 };
+	
+	itdev->want[unit][0] = mwdma_want[mode_wanted];
+	itdev->want[unit][1] = 2;	/* MWDMA is low priority */
+	
+	it8212_clock_strategy(drive);
+	
+	/* UDMA bits off */
+	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
+	conf |= 1 << (3 + 2 * channel + unit);
+	pci_write_config_byte(hwif->pci_dev, 0x50, conf);
+	
+	/* Program PIO/MWDMA timing bits */
+	pci_read_config_byte(hwif->pci_dev, 0x54 + 4 * channel, &conf);
+	if(itdev->clock_mode == 66)
+		conf = dma_66[mode_wanted];
+	else	
+		conf = dma_50[mode_wanted];
+	pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
+	itdev->mwdma[unit] = conf;	
+}
+
+/**
+ *	it8212_tune_udma	-	tune a channel for UDMA
+ *	@drive: drive to set up
+ *	@mode_wanted: the target operating mode
+ *
+ *	Load the timing settings for this device mode into the
+ *	controller when doing UDMA modes in pass through.
+ */
+ 
+static void it8212_tune_udma (ide_drive_t *drive, byte mode_wanted)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
+	int unit = drive->select.b.unit;
+	int channel = hwif->channel;
+	u8 conf;
+
+	static u8 udma_50[]= { 0x33, 0x31, 0x21, 0x21, 0x11, 0x11, 0x11 };
+	static u8 udma_66[]= { 0x44, 0x42, 0x31, 0x21, 0x11, 0x22, 0x11 };
+	
+	static u8 udma_want[]	= { 0, 50, 0, 66, 66, 50, 66 };
+	
+	itdev->want[unit][0] = udma_want[mode_wanted];
+	itdev->want[unit][1] = 3;	/* UDMA is high priority */
+	
+	it8212_clock_strategy(drive);
+	
+	/* UDMA on */
+	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
+	conf &= ~ (1 << (3 + 2 * channel + unit));
+	pci_write_config_byte(hwif->pci_dev, 0x50, conf);
+	
+	/* Program UDMA timing bits */
+	pci_read_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, &conf);
+	if(itdev->clock_mode == 66)
+		conf = udma_66[mode_wanted];
+	else
+		conf = udma_50[mode_wanted];
+	
+	if(mode_wanted >= 5)
+		conf |= 0x80;	/* UDMA 5/6 select on */
+		
+	pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf);
+	itdev->mwdma[unit] = 0;
+}
+
+/**
+ *	config_it8212_chipset_for_pio	-	set drive timings
+ *	@drive: drive to tune
+ *	@speed we want
+ *
+ *	Compute the best pio mode we can for a given device. We must
+ *	pick a speed that does not cause problems with the other device
+ *	on the cable.
+ */
+ 
+static void config_it8212_chipset_for_pio (ide_drive_t *drive, byte set_speed)
+{
+	u8 unit = drive->select.b.unit;
+	ide_hwif_t *hwif = HWIF(drive);
+	ide_drive_t *pair = &hwif->drives[1-unit];
+	u8 speed = 0, set_pio	= ide_get_best_pio_mode(drive, 4, 5, NULL);
+	u8 pair_pio;
+	
+	/* We have to deal with this mess in pairs */
+	if(pair != NULL)
+	{
+		pair_pio = ide_get_best_pio_mode(pair, 4, 5, NULL);
+		/* Trim PIO to the slowest of the master/slave */
+		if(pair_pio < set_pio)
+			set_pio = pair_pio;
+	}
+	it8212_tuneproc(drive, set_pio);
+	speed = XFER_PIO_0 + set_pio;
+	/* XXX - We trim to the lowest of the pair so the other drive
+	   will always be fine at this point until we do hotplug passthru */
+	   
+	if (set_speed)
+		(void) ide_config_drive_speed(drive, speed);
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
+{
+	config_it8212_chipset_for_pio(drive, set_speed);
+}
+
+/**
+ *	it8212_dma_read	-	DMA hook
+ *	@drive: drive for DMA
+ *
+ *	The IT8212 has a single timing register for MWDMA and for PIO
+ *	operations. As we flip back and forth we have to reload the
+ *	clock.
+ *
+ *	FIXME: for 0x10 model we should reprogram UDMA here
+ */
+ 
+static int it8212_dma_begin(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
+	int unit = drive->select.b.unit;
+	if(itdev->mwdma[unit])
+		pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * hwif->channel, itdev->mwdma[drive->select.b.unit]);
+	return __ide_dma_begin(drive);
+}
+
+/**
+ *	it8212_dma_write	-	DMA hook
+ *	@drive: drive for DMA stop
+ *
+ *	The IT8212 has a single timing register for MWDMA and for PIO
+ *	operations. As we flip back and forth we have to reload the
+ *	clock.
+ *
+ *	FIXME: for 0x10 model we should reprogram UDMA here
+ */
+ 
+static int it8212_dma_end(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	int unit = drive->select.b.unit;
+	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
+	int ret = __ide_dma_end(drive);
+	
+	if(itdev->mwdma[unit])
+		pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * hwif->channel, itdev->pio[drive->select.b.unit]);
+	return ret;
+}
+
+	
+/**
+ *	it8212_tune_chipset	-	set controller timings
+ *	@drive: Drive to set up
+ *	@xferspeed: speed we want to achieve
+ *
+ *	Tune the ITE chipset for the desired mode. If we can't achieve
+ *	the desired mode then tune for a lower one, but ultimately
+ *	make the thing work.
+ */
+ 
+static int it8212_tune_chipset (ide_drive_t *drive, byte xferspeed)
+{
+
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct it8212_dev *itdev = ide_get_hwifdata(hwif);
+	u8 speed		= ide_rate_filter(it8212_ratemask(drive), xferspeed);
+				    
+	switch(speed) {
+		case XFER_PIO_4:
+		case XFER_PIO_3:
+		case XFER_PIO_2:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+			if(!itdev->smart)
+				it8212_tuneproc(drive, (speed - XFER_PIO_0));
+			break;
+		/* MWDMA tuning is really hard because our MWDMA and PIO
+		   timings are kept in the same place. We can switch in the 
+		   host dma on/off callbacks */
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:
+		case XFER_MW_DMA_0:
+			if(!itdev->smart)
+				it8212_tune_mwdma(drive, (speed - XFER_MW_DMA_0));
+			break;
+		case XFER_UDMA_6:
+		case XFER_UDMA_5:
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+			if(!itdev->smart)
+				it8212_tune_udma(drive, (speed - XFER_UDMA_0));
+			break;
+		default:
+			return 1;
+	}
+	/*
+	 *	In smart mode the clocking is done by the host controller
+	 * 	snooping the mode we picked. The rest of it is not our problem
+	 */
+	return (ide_config_drive_speed(drive, speed));
+}
+
+/**
+ *	config_chipset_for_dma	-	configure for DMA
+ *	@drive: drive to configure
+ *
+ *	Called by the IDE layer when it wants the timings set up.
+ */
+ 
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+	u8 speed	= ide_dma_speed(drive, it8212_ratemask(drive));
+
+	config_chipset_for_pio(drive, !speed);
+
+	if (!speed)
+		return 0;
+
+	if (ide_set_xfer_rate(drive, speed))
+		return 0;
+
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
+	return ide_dma_enable(drive);
+}
+
+/**
+ *	it8212_configure_drive_for_dma	-	set up for DMA transfers
+ *	@drive: drive we are going to set up
+ *
+ *	Set up the drive for DMA, tune the controller and drive as 
+ *	required. If the drive isn't suitable for DMA or we hit
+ *	other problems then we will drop down to PIO and set up
+ *	PIO appropriately
+ */
+ 
+static int it8212_config_drive_for_dma (ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct hd_driveid *id	= drive->id;
+
+	if ((id->capability & 1) != 0 && drive->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (__ide_dma_bad_drive(drive))
+			goto fast_ata_pio;
+
+		if ((id->field_valid & 4) && it8212_ratemask(drive)) {
+			if (id->dma_ultra & hwif->ultra_mask) {
+				/* Force if Capable UltraDMA */
+				int dma = config_chipset_for_dma(drive);
+				if ((id->field_valid & 2) && !dma)
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & hwif->mwdma_mask) ||
+			    (id->dma_1word & hwif->swdma_mask)) {
+				/* Force if Capable regular DMA modes */
+				if (!config_chipset_for_dma(drive))
+					goto no_dma_set;
+			}
+		} else if (__ide_dma_good_drive(drive) &&
+			   (id->eide_dma_time < 150)) {
+			/* Consult the list of known "good" drives */
+			if (!config_chipset_for_dma(drive))
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+		return hwif->ide_dma_on(drive);
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+no_dma_set:
+		config_chipset_for_pio(drive, 1);
+		return hwif->ide_dma_off_quietly(drive);
+	}
+	/* IORDY not supported */
+	return 0;
+}
+
+/**
+ *	init_chipset_it8212	-	set up an ITE device
+ *	@dev: PCI device
+ *	@name: device name
+ *
+ */
+
+static unsigned int __devinit init_chipset_it8212(struct pci_dev *dev, const char *name)
+{
+	return 0;
+}
+
+/**
+ *	ata66_it8212	-	check for 80 pin cable
+ *	@hwif: interface to check
+ *
+ *	Check for the presence of an ATA66 capable cable on the
+ *	interface. Note that the firmware writes bits 4-7 having done 
+ *	the drive side sampling. This may impact hotplug.
+ */
+
+static unsigned int __devinit ata66_it8212(ide_hwif_t *hwif)
+{
+	u16 iocfg;
+	
+	pci_read_config_word(hwif->pci_dev, 0x40, &iocfg);
+	if(iocfg & (1 << (4 + 2*hwif->channel)))
+		return 1;
+	return 0;
+}
+
+/**
+ *	init_hwif_it8212	-	set up hwif structs
+ *	@hwif: interface to set up
+ *
+ *	We do the basic set up of the interface structure. The IT8212
+ *	requires several custom handlers so we override the default
+ *	ide DMA handlers appropriately
+ */
+
+static void __devinit init_hwif_it8212(ide_hwif_t *hwif)
+{
+	struct it8212_dev *idev = kmalloc(sizeof(struct it8212_dev), GFP_KERNEL);
+	u8 conf;
+	
+	if(idev == NULL)
+	{
+		printk(KERN_ERR "it8212: out of memory, falling back to legacy behaviour.\n");
+		goto fallback;
+	}
+	memset(idev, 0, sizeof(*idev));
+	ide_set_hwifdata(hwif, idev);
+	
+	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
+	if(conf & 1)
+	{
+		if(hwif->channel == 0)
+			printk(KERN_INFO "it8212: controller in RAID mode.\n");
+		idev->smart = 1;
+	}
+	else if(hwif->channel == 1)
+		printk(KERN_INFO "it8212: controller in pass through mode.\n");
+		
+	/*
+	 *	Not in the docs but according to the reference driver
+	 *	this is neccessary.
+	 */
+	pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
+	if(conf == 0x10)
+		idev->timing10 = 1;
+#if 0	/* Needs more research */
+	else
+		hwif->atapi_dma = 1;
+#endif
+
+	if(idev->timing10 && !idev->smart)
+	{
+		printk(KERN_WARNING "it8212: DMA is not currently supported on revision 0x10 in pass through.\n");
+		goto fallback;
+	}
+		
+	hwif->speedproc = &it8212_tune_chipset;
+	hwif->tuneproc	= &it8212_tuneproc;
+	
+	/* MWDMA/PIO clock switching for pass through mode */
+	if(!idev->smart)
+	{
+		hwif->ide_dma_begin = &it8212_dma_begin;
+		hwif->ide_dma_end = &it8212_dma_end;
+	}
+
+	if (!hwif->dma_base)
+		goto fallback;
+
+	hwif->ultra_mask = 0x7f;
+	hwif->mwdma_mask = 0x07;
+	hwif->swdma_mask = 0x07;
+	
+
+	hwif->ide_dma_check = &it8212_config_drive_for_dma;
+	if (!(hwif->udma_four))
+		hwif->udma_four = ata66_it8212(hwif);
+
+	/*
+	 *	The BIOS often doesn't set up DMA on this controller
+	 *	so we always do it.
+	 */
+
+	hwif->autodma = 1;
+	hwif->drives[0].autodma = hwif->autodma;
+	hwif->drives[1].autodma = hwif->autodma;
+	return;
+
+fallback:
+	hwif->autodma = 0;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+	return;
+}
+
+#define DECLARE_ITE_DEV(name_str)			\
+	{						\
+		.name		= name_str,		\
+		.init_chipset	= init_chipset_it8212,	\
+		.init_hwif	= init_hwif_it8212,	\
+		.channels	= 2,			\
+		.autodma	= AUTODMA,		\
+		.bootable	= ON_BOARD,		\
+	}
+
+static ide_pci_device_t it8212_chipsets[] __devinitdata = {
+	/* 0 */ DECLARE_ITE_DEV("IT8212"),
+};
+
+/**
+ *	it8212_init_one	-	pci layer discovery entry
+ *	@dev: PCI device
+ *	@id: ident table entry
+ *
+ *	Called by the PCI code when it finds an ITE8212 controller.
+ *	We then use the IDE PCI generic helper to do most of the work.
+ */
+ 
+static int __devinit it8212_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	ide_setup_pci_device(dev, &it8212_chipsets[id->driver_data]);
+	return 0;
+}
+
+static struct pci_device_id it8212_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, it8212_pci_tbl);
+
+static struct pci_driver driver = {
+	.name		= "ITE8212 IDE",
+	.id_table	= it8212_pci_tbl,
+	.probe		= it8212_init_one,
+};
+
+static int it8212_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+module_init(it8212_ide_init);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("PCI driver module for the ITE 8212");
+MODULE_LICENSE("GPL");
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.8-rc2/drivers/ide/pci/Makefile linux-2.6.8-rc2/drivers/ide/pci/Makefile
--- linux.vanilla-2.6.8-rc2/drivers/ide/pci/Makefile	2004-07-27 19:21:37.000000000 +0100
+++ linux-2.6.8-rc2/drivers/ide/pci/Makefile	2004-07-31 17:16:01.000000000 +0100
@@ -13,6 +13,7 @@
 obj-$(CONFIG_BLK_DEV_HPT366)		+= hpt366.o
 #obj-$(CONFIG_BLK_DEV_HPT37X)		+= hpt37x.o
 obj-$(CONFIG_BLK_DEV_IT8172)		+= it8172.o
+obj-$(CONFIG_BLK_DEV_IT8212)		+= it8212.o
 obj-$(CONFIG_BLK_DEV_NS87415)		+= ns87415.o
 obj-$(CONFIG_BLK_DEV_OPTI621)		+= opti621.o
 obj-$(CONFIG_BLK_DEV_PDC202XX_OLD)	+= pdc202xx_old.o


----- End forwarded message -----

-- 
--
  "Have you noticed the way people's intelligence capabilities decline
   sharply the minute they start waving guns around?"
 		-- Dr. Who

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2004-08-14 20:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <2obsK-5Ni-13@gated-at.bofh.it>
2004-08-03 11:16 ` PATCH: Add support for IT8212 IDE controllers Elmar Hinz
2004-08-03 10:50   ` Alan Cox
2004-08-03 12:18     ` Elmar Hinz
2004-08-03 20:42       ` Elmar Hinz
2004-08-04 14:03 ` Elmar Hinz
2004-08-05 10:47   ` Alan Cox
2004-08-06 21:58     ` Elmar Hinz
2004-08-14 19:32   ` Alan Cox
2004-07-31 23:22 Alan Cox
2004-08-01 19:22 ` Ian Hastie
2004-08-01 20:10   ` Alan Cox
2004-08-01 23:05   ` Alan Cox
2004-08-06  0:45     ` Ian Hastie

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.