-
/*
- * linux/drivers/ide/pci/it821x.c Version 0.10 Mar 10 2007
- *
* Copyright (C) 2004 Red Hat <alan@redhat.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
/*
* We allow users to force the card into non raid mode without
- * flashing the alternative BIOS. This is also neccessary right now
+ * flashing the alternative BIOS. This is also necessary right now
* for embedded platforms that cannot run a PC BIOS but are using this
* device.
*/
static void it821x_program(ide_drive_t *drive, u16 timing)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int channel = hwif->channel;
u8 conf;
conf = timing >> 8;
else
conf = timing & 0xFF;
- pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
+
+ pci_write_config_byte(dev, 0x54 + 4 * channel, conf);
}
/**
static void it821x_program_udma(ide_drive_t *drive, u16 timing)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int channel = hwif->channel;
int unit = drive->select.b.unit;
conf = timing >> 8;
else
conf = timing & 0xFF;
- if(itdev->timing10 == 0)
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf);
+
+ if (itdev->timing10 == 0)
+ pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf);
else {
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf);
- pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf);
+ pci_write_config_byte(dev, 0x56 + 4 * channel, conf);
+ pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf);
}
}
static void it821x_clock_strategy(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
u8 unit = drive->select.b.unit;
itdev->clock_mode = ATA_50;
sel = 1;
}
- pci_read_config_byte(hwif->pci_dev, 0x50, &v);
+
+ pci_read_config_byte(dev, 0x50, &v);
v &= ~(1 << (1 + hwif->channel));
v |= sel << (1 + hwif->channel);
- pci_write_config_byte(hwif->pci_dev, 0x50, v);
+ pci_write_config_byte(dev, 0x50, v);
/*
* Reprogram the UDMA/PIO of the pair drive for the switch
}
/**
- * it821x_tunepio - tune a drive
- * @drive: drive to tune
- * @pio: the desired PIO mode
+ * it821x_set_pio_mode - set host controller for PIO mode
+ * @drive: drive
+ * @pio: PIO mode number
*
- * Try to tune the drive/host to the desired PIO mode taking into
- * the consideration the maximum PIO mode supported by the other
- * device on the cable.
+ * Tune the host to the desired PIO mode taking into the consideration
+ * the maximum PIO mode supported by the other device on the cable.
*/
-static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
+static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = drive->hwif;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int unit = drive->select.b.unit;
ide_drive_t *pair = &hwif->drives[1 - unit];
+ u8 set_pio = pio;
/* Spec says 89 ref driver uses 88 */
- static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
+ static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
/*
* on the cable.
*/
if (pair) {
- u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL);
+ u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
/* trim PIO to the slowest of the master/slave */
if (pair_pio < set_pio)
set_pio = pair_pio;
}
- if (itdev->smart)
- goto set_drive_speed;
-
/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
itdev->want[unit][1] = pio_want[set_pio];
itdev->want[unit][0] = 1; /* PIO is lowest priority */
- itdev->pio[unit] = pio[set_pio];
+ itdev->pio[unit] = pio_timings[set_pio];
it821x_clock_strategy(drive);
it821x_program(drive, itdev->pio[unit]);
-
-set_drive_speed:
- return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
-}
-
-static void it821x_tuneproc(ide_drive_t *drive, u8 pio)
-{
- pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
- (void)it821x_tunepio(drive, pio);
}
/**
static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
int unit = drive->select.b.unit;
int channel = hwif->channel;
itdev->udma[unit] = UDMA_OFF;
/* UDMA bits off - Revision 0x10 do them in pairs */
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(itdev->timing10)
+ pci_read_config_byte(dev, 0x50, &conf);
+ if (itdev->timing10)
conf |= channel ? 0x60: 0x18;
else
conf |= 1 << (3 + 2 * channel + unit);
- pci_write_config_byte(hwif->pci_dev, 0x50, conf);
+ pci_write_config_byte(dev, 0x50, conf);
it821x_clock_strategy(drive);
/* FIXME: do we need to program this ? */
static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
{
- ide_hwif_t *hwif = drive->hwif;
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
int unit = drive->select.b.unit;
int channel = hwif->channel;
itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */
/* UDMA on. Again revision 0x10 must do the pair */
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(itdev->timing10)
+ pci_read_config_byte(dev, 0x50, &conf);
+ if (itdev->timing10)
conf &= channel ? 0x9F: 0xE7;
else
conf &= ~ (1 << (3 + 2 * channel + unit));
- pci_write_config_byte(hwif->pci_dev, 0x50, conf);
+ pci_write_config_byte(dev, 0x50, conf);
it821x_clock_strategy(drive);
it821x_program_udma(drive, itdev->udma[unit]);
return ret;
}
-
/**
- * it821x_tune_chipset - set controller timings
- * @drive: Drive to set up
- * @xferspeed: speed we want to achieve
+ * it821x_set_dma_mode - set host controller for DMA mode
+ * @drive: drive
+ * @speed: DMA mode
*
- * 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.
+ * Tune the ITE chipset for the desired DMA mode.
*/
-static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
+static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
-
- ide_hwif_t *hwif = drive->hwif;
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- u8 speed = ide_rate_filter(drive, xferspeed);
-
- switch (speed) {
- case XFER_PIO_4:
- case XFER_PIO_3:
- case XFER_PIO_2:
- case XFER_PIO_1:
- case XFER_PIO_0:
- return it821x_tunepio(drive, speed - XFER_PIO_0);
- }
-
- if (itdev->smart == 0) {
- switch (speed) {
- /* 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:
- it821x_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:
- it821x_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
+ * 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.
*/
- return ide_config_drive_speed(drive, speed);
-}
-
-/**
- * it821x_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 it821x_config_drive_for_dma (ide_drive_t *drive)
-{
- if (ide_tune_dma(drive))
- return 0;
-
- it821x_tuneproc(drive, 255);
-
- return -1;
+ if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_6)
+ it821x_tune_udma(drive, speed - XFER_UDMA_0);
+ else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
+ it821x_tune_mwdma(drive, speed - XFER_MW_DMA_0);
}
/**
* the needed logic onboard.
*/
-static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif)
+static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
{
/* The reference driver also only does disk side */
- return 1;
+ return ATA_CBL_PATA80;
}
/**
- * it821x_fixup - post init callback
- * @hwif: interface
+ * it821x_quirkproc - post init callback
+ * @drive: drive
*
- * This callback is run after the drives have been probed but
+ * This callback is run after the drive has been probed but
* before anything gets attached. It allows drivers to do any
* final tuning that is needed, or fixups to work around bugs.
*/
-static void __devinit it821x_fixups(ide_hwif_t *hwif)
+static void __devinit it821x_quirkproc(ide_drive_t *drive)
{
- struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- int i;
+ struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif);
+ struct hd_driveid *id = drive->id;
+ u16 *idbits = (u16 *)drive->id;
- if(!itdev->smart) {
+ if (!itdev->smart) {
/*
* If we are in pass through mode then not much
* needs to be done, but we do bother to clear the
* IRQ mask as we may well be in PIO (eg rev 0x10)
* for now and we know unmasking is safe on this chipset.
*/
- for (i = 0; i < 2; i++) {
- ide_drive_t *drive = &hwif->drives[i];
- if(drive->present)
- drive->unmask = 1;
- }
- return;
- }
+ drive->unmask = 1;
+ } else {
/*
* Perform fixups on smart mode. We need to "lose" some
* capabilities the firmware lacks but does not filter, and
* in RAID mode.
*/
- for(i = 0; i < 2; i++) {
- ide_drive_t *drive = &hwif->drives[i];
- struct hd_driveid *id;
- u16 *idbits;
-
- if(!drive->present)
- continue;
- id = drive->id;
- idbits = (u16 *)drive->id;
-
/* Check for RAID v native */
if(strstr(id->model, "Integrated Technology Express")) {
/* In raid mode the ident block is slightly buggy
if(idbits[129] != 1)
printk("(%dK stripe)", idbits[146]);
printk(".\n");
- /* Now the core code will have wrongly decided no DMA
- so we need to fix this */
- hwif->dma_off_quietly(drive);
-#ifdef CONFIG_IDEDMA_ONLYDISK
- if (drive->media == ide_disk)
-#endif
- ide_set_dma(drive);
} else {
/* Non RAID volume. Fixups to stop the core code
doing unsupported things */
- id->field_valid &= 1;
+ id->field_valid &= 3;
id->queue_depth = 0;
id->command_set_1 = 0;
id->command_set_2 &= 0xC400;
printk(KERN_INFO "%s: Performing identify fixups.\n",
drive->name);
}
+
+ /*
+ * Set MWDMA0 mode as enabled/support - just to tell
+ * IDE core that DMA is supported (it821x hardware
+ * takes care of DMA mode programming).
+ */
+ if (id->capability & 1) {
+ id->dma_mword |= 0x0101;
+ drive->current_speed = XFER_MW_DMA_0;
+ }
}
}
static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
{
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
u8 conf;
- if(idev == NULL) {
+ hwif->quirkproc = &it821x_quirkproc;
+
+ if (idev == NULL) {
printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
- goto fallback;
+ return;
}
- ide_set_hwifdata(hwif, idev);
- hwif->atapi_dma = 1;
+ ide_set_hwifdata(hwif, idev);
- pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
- if(conf & 1) {
+ pci_read_config_byte(dev, 0x50, &conf);
+ if (conf & 1) {
idev->smart = 1;
- hwif->atapi_dma = 0;
+ hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
/* Long I/O's although allowed in LBA48 space cause the
onboard firmware to enter the twighlight zone */
hwif->rqsize = 256;
/*
* Not in the docs but according to the reference driver
- * this is neccessary.
+ * this is necessary.
*/
- pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
- if(conf == 0x10) {
+ pci_read_config_byte(dev, 0x08, &conf);
+ if (conf == 0x10) {
idev->timing10 = 1;
- hwif->atapi_dma = 0;
- if(!idev->smart)
+ hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+ if (idev->smart == 0)
printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n");
}
- hwif->speedproc = &it821x_tune_chipset;
- hwif->tuneproc = &it821x_tuneproc;
+ if (idev->smart == 0) {
+ hwif->set_pio_mode = &it821x_set_pio_mode;
+ hwif->set_dma_mode = &it821x_set_dma_mode;
- /* MWDMA/PIO clock switching for pass through mode */
- if(!idev->smart) {
+ /* MWDMA/PIO clock switching for pass through mode */
hwif->dma_start = &it821x_dma_start;
hwif->ide_dma_end = &it821x_dma_end;
- }
+ } else
+ hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
- if (!hwif->dma_base)
- goto fallback;
-
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
+ if (hwif->dma_base == 0)
+ return;
- hwif->ide_dma_check = &it821x_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_it821x(hwif);
+ hwif->ultra_mask = ATA_UDMA6;
+ hwif->mwdma_mask = ATA_MWDMA2;
- /*
- * 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;
- return;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_it821x(hwif);
}
static void __devinit it8212_disable_raid(struct pci_dev *dev)
.name = name_str, \
.init_chipset = init_chipset_it821x, \
.init_hwif = init_hwif_it821x, \
- .channels = 2, \
- .autodma = AUTODMA, \
- .bootable = ON_BOARD, \
- .fixup = it821x_fixups \
+ .host_flags = IDE_HFLAG_BOOTABLE, \
+ .pio_mask = ATA_PIO4, \
}
-static ide_pci_device_t it821x_chipsets[] __devinitdata = {
+static const struct ide_port_info it821x_chipsets[] __devinitdata = {
/* 0 */ DECLARE_ITE_DEV("IT8212"),
};
static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
- return 0;
+ return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
}
-static struct pci_device_id it821x_pci_tbl[] = {
- { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id it821x_pci_tbl[] = {
+ { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 },
+ { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 },
{ 0, },
};