* [PATCH/RFC] Port of pdc202xx_new driver to libata
@ 2004-10-13 10:06 Albert Lee
2004-10-13 19:32 ` Bartlomiej Zolnierkiewicz
0 siblings, 1 reply; 11+ messages in thread
From: Albert Lee @ 2004-10-13 10:06 UTC (permalink / raw)
To: Jeff Garzik, bzolnier; +Cc: IDE Linux
Hi, Jeff and Bart:
I am trying to port the Promise pdc202xx_new driver to libata and adding
the
PLL tuning code to it. (The motivation is hotplug of the Promise host
adapter.)
The ported driver has been tested with pdc20269 and pdc20275 on i386 and
x86_64 boxes, with 33 MHz PCI bus and 66 MHz PCI bus respectively.
It seems to be working fine with harddisk drives.
(However, CD-ROM drives not working yet, even when
ATA_ENABLE_PATA and ATA_ENABLE_ATAPI are enabled.)
My question is, in the current kernel, the IDE subsystem drives PATA chips
and libata drives SATA chips. Will PATA driver like this be accepted into
libata?
Thanks,
Albert Lee
(The patch is against 2.6.8.1.)
********************************************************************
diff -Nru linux-2.6.8.1/drivers/scsi/Kconfig
linux-2.6.8.1-mod/drivers/scsi/Kconfig
--- linux-2.6.8.1/drivers/scsi/Kconfig 2004-08-14 18:56:14.000000000 +0800
+++ linux-2.6.8.1-mod/drivers/scsi/Kconfig 2004-10-13 15:38:23.000000000
+0800
@@ -441,6 +441,14 @@
If unsure, say N.
+config SCSI_PATA_PDC_NEW
+ tristate "Promise PATA 202xx new support"
+ depends on SCSI_SATA && PCI
+ help
+ This option enables support for Promise PATA pdc20268 to pdc20277 Host
Adapters.
+
+ If unsure, say N.
+
config SCSI_SATA_PROMISE
tristate "Promise SATA TX2/TX4 support"
depends on SCSI_SATA && PCI
diff -Nru linux-2.6.8.1/drivers/scsi/Makefile
linux-2.6.8.1-mod/drivers/scsi/Makefile
--- linux-2.6.8.1/drivers/scsi/Makefile 2004-08-14 18:55:59.000000000 +0800
+++ linux-2.6.8.1-mod/drivers/scsi/Makefile 2004-10-13 15:38:26.000000000
+0800
@@ -121,6 +121,7 @@
obj-$(CONFIG_SCSI_IPR) += ipr.o
obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o
obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o
+obj-$(CONFIG_SCSI_PATA_PDC_NEW) += libata.o pata_pdc202xx_new.o
obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o
obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o
obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o
diff -Nru linux-2.6.8.1/drivers/scsi/pata_pdc202xx_new.c
linux-2.6.8.1-mod/drivers/scsi/pata_pdc202xx_new.c
--- linux-2.6.8.1/drivers/scsi/pata_pdc202xx_new.c 1970-01-01
08:00:00.000000000 +0800
+++ linux-2.6.8.1-mod/drivers/scsi/pata_pdc202xx_new.c 2004-10-13
16:52:11.000000000 +0800
@@ -0,0 +1,721 @@
+/*
+ * Promise PATA TX2/TX4/TX2000/133 IDE driver for pdc20268 to pdc20277.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Ported to libata by:
+ * Albert Lee <albertcc@tw.ibm.com> IBM Corporation
+ *
+ * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>
+ * Portions Copyright (C) 1999 Promise Technology, Inc.
+ *
+ * Author: Frank Tiernan (frankt@promise.com)
+ * Released under terms of General Public License
+ *
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME "pata_pdc202xx_new"
+#define DRV_VERSION "0.50"
+#undef PDC_DEBUG
+
+#ifdef PDC_DEBUG
+#define PDPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__,
## args)
+#else
+#define PDPRINTK(fmt, args...)
+#endif
+
+enum {
+ PDC_UDMA_100 = 0,
+ PDC_UDMA_133 = 1,
+
+ PDC_100_MHZ = 100000000,
+ PDC_133_MHZ = 133333333,
+};
+
+static int pdc_new_init_one(struct pci_dev *pdev, const struct
pci_device_id *ent);
+static void pdc_new_remove_one(struct pci_dev *pdev);
+static void pdc_new_phy_reset(struct ata_port *ap);
+static void pdc_new_set_piomode(struct ata_port *ap, struct ata_device
*adev, unsigned int pio);
+static void pdc_new_set_udmamode(struct ata_port *ap, struct ata_device
*adev, unsigned int udma);
+
+static struct pdc_pata_ide_controller {
+ char* chip_name;
+ int max_udma_mode;
+ long pll_pout_required;
+} pdc_pata_controller_tbl [] = {
+ { "Ultra100 TX2", PDC_UDMA_100, PDC_100_MHZ }, /* pdc20268 */
+ { "Ultra133 TX2", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20269 */
+ { "FastTrak LP/TX2/TX4", PDC_UDMA_100, PDC_100_MHZ }, /* pdc20270 */
+ { "FastTrak TX2000", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20271 */
+ { "MBUltra133", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20275 */
+ { "MBFastTrak 133 Lite", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20276 */
+ { "SBFastTrak 133 Lite", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20277 */
+};
+
+static struct pci_device_id pdc_new_pci_tbl[] = {
+#ifdef ATA_ENABLE_PATA
+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 1 },
+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 2 },
+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 3 },
+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 4 },
+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 5 },
+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 6 },
+#endif
+ { } /* terminate list */
+};
+
+static struct pci_driver pdc_new_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = pdc_new_pci_tbl,
+ .probe = pdc_new_init_one,
+ .remove = __devexit_p(pdc_new_remove_one),
+};
+
+static Scsi_Host_Template pdc_new_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .queuecommand = ata_scsi_queuecmd,
+ .eh_strategy_handler = ata_scsi_error,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations pdc_new_pata_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = pdc_new_set_piomode,
+ .set_udmamode = pdc_new_set_udmamode,
+
+ .tf_load = ata_tf_load_pio,
+ .tf_read = ata_tf_read_pio,
+ .exec_command = ata_exec_command_pio,
+ .check_status = ata_check_status_pio,
+
+ .phy_reset = pdc_new_phy_reset,
+
+ .bmdma_setup = ata_bmdma_setup_pio,
+ .bmdma_start = ata_bmdma_start_pio,
+ //.fill_sg = ata_fill_sg,
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .eng_timeout = ata_eng_timeout,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+};
+
+static struct ata_port_info pdc_new_port_info[] = {
+ /* PDC_UDMA_100 */
+ {
+ .sht = &pdc_new_sht,
+ .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
+ ATA_FLAG_SRST, /* | ATA_FLAG_MMIO, */
+ .pio_mask = 0x03, /* pio3-4 */
+ .udma_mask = ATA_UDMA5,
+ .port_ops = &pdc_new_pata_ops,
+ },
+ /* PDC_UDMA_133 */
+ {
+ .sht = &pdc_new_sht,
+ .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
+ ATA_FLAG_SRST,
+ .pio_mask = 0x03, /* pio3-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &pdc_new_pata_ops,
+ },
+};
+
+MODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Albert Lee");
+MODULE_DESCRIPTION("libata driver module for Promise PDC20268 to
PDC20277");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, pdc_new_pci_tbl);
+
+/**
+ * pdc_get_indexed_reg - Set pdc202xx extended register
+ * @ap: Port to which the extended register is set
+ * @index: index of the extended register
+ */
+static u8 pdc_get_indexed_reg(struct ata_port *ap, u8 index)
+{
+ u8 tmp8;
+
+ outb(index, ap->ioaddr.bmdma_addr + 1);
+ tmp8 = inb(ap->ioaddr.bmdma_addr + 3);
+
+ PDPRINTK("Get index reg%X[%X] \n", index, tmp8);
+ return tmp8;
+}
+/**
+ * pdc_set_indexed_reg - Read pdc202xx extended register
+ * @ap: Port to which the extended register is read
+ * @index: index of the extended register
+ */
+static void pdc_set_indexed_reg(struct ata_port *ap, u8 index, u8 value)
+{
+ outb(index, ap->ioaddr.bmdma_addr + 1);
+ outb(value, ap->ioaddr.bmdma_addr + 3);
+ PDPRINTK("Set index reg%X[%X] \n", index, value);
+}
+/**
+ * pdc_set_pio - Set the PIO extended registers
+ * @ap: Port to which the extended register is set
+ * @adev: Device to set
+ * @value0: value for extended register at 0x0c
+ * @value1: value for extended register at 0x0d
+ * @value2: value for extended register at 0x13
+ */
+static void pdc_set_pio(struct ata_port *ap, struct ata_device *adev, u8
value0, u8 value1, u8 value2)
+{
+ unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno;
+ u8 adj = (drive_dn%2) ? 0x08 : 0x00;
+
+ PDPRINTK("Set pio regs... \n");
+
+ pdc_set_indexed_reg(ap, 0x0c + adj, value0);
+ pdc_set_indexed_reg(ap, 0x0d + adj, value1);
+ pdc_set_indexed_reg(ap, 0x13 + adj, value2);
+
+ PDPRINTK("Set pio regs done\n");
+}
+/**
+ * pdc_set_ultra - Set the UDMA extended registers
+ * @ap: Port to which the extended register is set
+ * @adev: Device to set
+ * @value0: value for extended register at 0x10
+ * @value1: value for extended register at 0x11
+ * @value2: value for extended register at 0x12
+ */
+static void pdc_set_ultra(struct ata_port *ap, struct ata_device *adev, u8
value0, u8 value1, u8 value2)
+{
+ unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno;
+ u8 adj = (drive_dn%2) ? 0x08 : 0x00;
+
+ PDPRINTK("Set udma regs... \n");
+ pdc_set_indexed_reg(ap, 0x10 + adj, value0);
+ pdc_set_indexed_reg(ap, 0x11 + adj, value1);
+ pdc_set_indexed_reg(ap, 0x12 + adj, value2);
+
+ PDPRINTK("Set udma regs done\n");
+}
+/**
+ * pdc_new_pata_cbl_detect - Probe host controller cable detect info
+ * @ap: Port for which cable detect info is desired
+ *
+ * Read 80c cable indicator from Promise extended register.
+ * This register is normally set by firmware.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+static void pdc_new_cbl_detect(struct ata_port *ap)
+{
+ u8 cbl40c;
+
+ /* For UDMA33, no 80c support is required */
+ if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
+ goto cbl40;
+
+ /* check cable detect results */
+ cbl40c = pdc_get_indexed_reg(ap, 0x0b) & 0x04;
+
+ if (cbl40c)
+ goto cbl40;
+
+ PDPRINTK("No cable or 80-conductor cable on port %d\n", ap->port_no);
+
+ ap->cbl = ATA_CBL_PATA80;
+ return;
+
+cbl40:
+ printk(KERN_INFO DRV_NAME ": 40-conductor cable detected on port %d\n",
ap->port_no);
+ ap->cbl = ATA_CBL_PATA40;
+ ap->udma_mask &= ATA_UDMA_MASK_40C;
+}
+/**
+ * pdc_new_port_enabled - Check extended register at 0x04 to see whether
the port is enabled.
+ * @ap: Port to check
+ */
+static inline int pdc_new_port_enabled(struct ata_port *ap)
+{
+ return pdc_get_indexed_reg(ap, 0x04) & 0x02;
+}
+/**
+ * pdc_new_phy_reset - Probe specified port on PATA host controller
+ * @ap: Port to probe
+ *
+ * Probe PATA phy.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+static void pdc_new_phy_reset(struct ata_port *ap)
+{
+ /* Check whether port enabled */
+ if (!pdc_new_port_enabled(ap)) {
+ ata_port_disable(ap);
+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ return;
+ }
+
+ pdc_new_cbl_detect(ap);
+ ata_port_probe(ap);
+ ata_bus_reset(ap);
+}
+/**
+ * pdc_new_set_piomode - Initialize host controller PATA PIO timings
+ * @ap: Port to configure
+ * @adev: um
+ * @pio: PIO mode, 0 - 4
+ *
+ * Set PIO mode for device.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+static void pdc_new_set_piomode(struct ata_port *ap, struct ata_device
*adev, unsigned int pio)
+{
+ unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno;
+ u8 adj = (drive_dn%2) ? 0x08 : 0x00;
+ u8 tmp8;
+
+ switch (pio | 0x08) {
+ case XFER_PIO_4:
+ pdc_set_pio(ap, adev, 0x23, 0x09, 0x25); /* IORDY on, Prefetch off */
+ break;
+ case XFER_PIO_3:
+ pdc_set_pio(ap, adev, 0x27, 0x0d, 0x35); /* IORDY on, Prefetch off */
+ break;
+ //case XFER_PIO_2: pdc_set_pio(ap, adev, 0x23, 0x26, 0x64); break;
+ //case XFER_PIO_1: pdc_set_pio(ap, adev, 0x46, 0x29, 0xa4); break;
+ //case XFER_PIO_0: pdc_set_pio(ap, adev, 0xfb, 0x2b, 0xac); break;
+ default:
+ printk(KERN_ERR DRV_NAME ": Unknown pio mode [%d] ignored\n", pio);
+ return;
+ }
+
+ /*
+ * Check whether the device supports turning off IORDY.
+ * For PIO3 and above, the device must support IORDY and set bit 10
+ */
+ if (adev->id[49] & 0x400) {
+ /* IORDY_EN & PREFETCH_EN */
+ /* Turn on Prefetch */
+ tmp8 = pdc_get_indexed_reg(ap, 0x13 + adj);
+ pdc_set_indexed_reg(ap, 0x13 + adj, tmp8 | 0x03);
+
+ PDPRINTK("Turn on prefetch\n");
+ }
+
+ printk(KERN_INFO DRV_NAME ": Set to pio mode[%u] \n", pio);
+}
+/**
+ * pdc_new_set_udmamode - Initialize host controller PATA UDMA timings
+ * @ap: Port to configure
+ * @adev: um
+ * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6
+ *
+ * Set UDMA mode for device.
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ */
+static void pdc_new_set_udmamode(struct ata_port *ap, struct ata_device
*adev, unsigned int udma)
+{
+ unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno;
+
+ u8 adj = (drive_dn%2) ? 0x08 : 0x00;
+ u8 tmp8;
+
+ if (udma == XFER_UDMA_2) {
+ /*
+ * Turn off tHOLD.
+ * If tHOLD is '1', the hardware will add half clock for data hold time.
+ * This code segment seems to be no effect. tHOLD will be overwritten
below.
+ */
+ tmp8 = pdc_get_indexed_reg(ap, 0x10 + adj);
+ pdc_set_indexed_reg(ap, 0x10 + adj, tmp8 & 0x7f);
+ }
+
+ switch (udma) {
+ case XFER_UDMA_7:
+ udma = XFER_UDMA_6;
+ case XFER_UDMA_6: pdc_set_ultra(ap, adev, 0x1a, 0x01, 0xcb); break;
+ case XFER_UDMA_5: pdc_set_ultra(ap, adev, 0x1a, 0x02, 0xcb); break;
+ case XFER_UDMA_4: pdc_set_ultra(ap, adev, 0x1a, 0x03, 0xcd); break;
+ case XFER_UDMA_3: pdc_set_ultra(ap, adev, 0x1a, 0x05, 0xcd); break;
+ case XFER_UDMA_2: pdc_set_ultra(ap, adev, 0x2a, 0x07, 0xcd); break;
+ case XFER_UDMA_1: pdc_set_ultra(ap, adev, 0x3a, 0x0a, 0xd0); break;
+ case XFER_UDMA_0: pdc_set_ultra(ap, adev, 0x4a, 0x0f, 0xd5); break;
+ default:
+ printk(KERN_ERR DRV_NAME ": Unknown udma mode [%u] ignored\n", udma &
0x07);
+ return;
+ }
+
+ printk(KERN_INFO DRV_NAME ": Set to udma mode[%u] \n", udma & 0x07);
+}
+/**
+ * adjust_pll - Adjust the PLL input clock in Hz.
+ *
+ * @pdc_controller: controller specific information
+ * @probe_ent: For the port address
+ * @pll_clock: The input of PLL in HZ
+ */
+static void adjust_pll(struct pdc_pata_ide_controller* pdc_controller,
struct ata_probe_ent *probe_ent, long pll_clock)
+{
+
+ u8 pll_ctl0, pll_ctl1;
+ long pll_clock_khz = pll_clock / 1000;
+ long pout_required = pdc_controller->pll_pout_required;
+ long ratio = pout_required / pll_clock_khz;
+ int F, R;
+
+ /* Sanity check */
+ if (unlikely(pll_clock_khz < 5000L || pll_clock_khz > 70000L)) {
+ printk(KERN_ERR DRV_NAME ": Invalid PLL input clock %ldkHz, give up!\n",
pll_clock_khz);
+ return;
+ }
+
+#ifdef PDC_DEBUG
+ /* Show the current clock value of PLL control register
+ * (maybe already configured by the firmware)
+ */
+ outb(0x02, probe_ent->port[1].bmdma_addr + 0x01);
+ pll_ctl0 = inb(probe_ent->port[1].bmdma_addr + 0x03);
+ outb(0x03, probe_ent->port[1].bmdma_addr + 0x01);
+ pll_ctl1 = inb(probe_ent->port[1].bmdma_addr + 0x03);
+
+ printk(KERN_DEBUG DRV_NAME ": pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1);
+#endif
+
+ /*
+ * Calculate the ratio of F, R and OD
+ * POUT = (F + 2) / (( R + 2) * NO)
+ */
+ if (ratio < 8600L) { // 8.6x
+ /* Using NO = 0x01, R = 0x0D */
+ R = 0x0d;
+ } else if (ratio < 12900L) { // 12.9x
+ /* Using NO = 0x01, R = 0x08 */
+ R = 0x08;
+ } else if (ratio < 16100L) { // 16.1x
+ /* Using NO = 0x01, R = 0x06 */
+ R = 0x06;
+ } else if (ratio < 64000L) { // 64x
+ R = 0x00;
+ } else {
+ /* Invalid ratio */
+ printk(KERN_ERR DRV_NAME ": Invalid ratio %ld, give up!\n", ratio);
+ return;
+ }
+
+ F = (ratio * (R+2)) / 1000 - 2;
+
+ if (unlikely(F < 0 || F > 127)) {
+ /* Invalid F */
+ printk(KERN_ERR DRV_NAME ": F[%d] invalid!\n", F);
+ return;
+ }
+
+ PDPRINTK("F[%d] R[%d] ratio*1000[%ld]\n", F, R, ratio);
+
+ pll_ctl0 = (u8) F;
+ pll_ctl1 = (u8) R;
+
+ PDPRINTK("Writing pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1);
+
+ outb(0x02, probe_ent->port[1].bmdma_addr + 0x01);
+ outb(pll_ctl0, probe_ent->port[1].bmdma_addr + 0x03);
+ outb(0x03, probe_ent->port[1].bmdma_addr + 0x01);
+ outb(pll_ctl1, probe_ent->port[1].bmdma_addr + 0x03);
+
+ /* Wait the PLL circuit to be stable */
+ mdelay(30);
+
+#ifdef PDC_DEBUG
+ /*
+ * Show the current clock value of PLL control register
+ * (maybe configured by the firmware)
+ */
+ outb(0x02, probe_ent->port[1].bmdma_addr + 0x01);
+ pll_ctl0 = inb(probe_ent->port[1].bmdma_addr + 0x03);
+ outb(0x03, probe_ent->port[1].bmdma_addr + 0x01);
+ pll_ctl1 = inb(probe_ent->port[1].bmdma_addr + 0x03);
+
+ printk(KERN_DEBUG DRV_NAME ": pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1);
+#endif
+
+ return;
+}
+/**
+ * detect_pll_input_clock - Detect the PLL input clock in Hz.
+ * @probe_ent: for the port address
+ * Ex. 16949000 on 33MHz PCI bus for pdc20275.
+ * Half of the PCI clock.
+ */
+static long detect_pll_input_clock(struct ata_probe_ent *probe_ent)
+{
+ u8 scr1;
+ unsigned long ctr0;
+ unsigned long ctr1;
+ unsigned long ctr2 = 0;
+ unsigned long ctr3 = 0;
+
+ unsigned long start_count, end_count;
+ long pll_clock;
+
+ /* Read current counter value */
+ outb(0x20, probe_ent->port[0].bmdma_addr + 0x01);
+ ctr0 = inb(probe_ent->port[0].bmdma_addr + 0x03);
+ outb(0x21, probe_ent->port[0].bmdma_addr + 0x01);
+ ctr1 = inb(probe_ent->port[0].bmdma_addr + 0x03);
+
+ outb(0x20, probe_ent->port[1].bmdma_addr + 0x01);
+ ctr2 = inb(probe_ent->port[1].bmdma_addr + 0x03);
+ outb(0x21, probe_ent->port[1].bmdma_addr + 0x01);
+ ctr3 = inb(probe_ent->port[1].bmdma_addr + 0x03);
+
+ start_count = (ctr3 << 23 ) | (ctr2 << 15) | (ctr1 << 8) | ctr0;
+
+ PDPRINTK("ctr0[%lX] ctr1[%lX] ctr2 [%lX] ctr3 [%lX]\n", ctr0, ctr1, ctr2,
ctr3);
+
+ /* Start the test mode */
+ outb(0x01, probe_ent->port[0].bmdma_addr + 0x01);
+ scr1 = inb(probe_ent->port[0].bmdma_addr + 0x03);
+ PDPRINTK("scr1[%X]\n", scr1);
+ outb(scr1 | 0x40, probe_ent->port[0].bmdma_addr + 0x03);
+
+ /* Let the counter run for 1000 us. */
+ udelay(1000);
+
+ /* Read the counter values again */
+ outb(0x20, probe_ent->port[0].bmdma_addr + 0x01);
+ ctr0 = inb(probe_ent->port[0].bmdma_addr + 0x03);
+ outb(0x21, probe_ent->port[0].bmdma_addr + 0x01);
+ ctr1 = inb(probe_ent->port[0].bmdma_addr + 0x03);
+
+ outb(0x20, probe_ent->port[1].bmdma_addr + 0x01);
+ ctr2 = inb(probe_ent->port[1].bmdma_addr + 0x03);
+ outb(0x21, probe_ent->port[1].bmdma_addr + 0x01);
+ ctr3 = inb(probe_ent->port[1].bmdma_addr + 0x03);
+
+ end_count = (ctr3 << 23 ) | (ctr2 << 15) | (ctr1 << 8) | ctr0;
+
+ PDPRINTK("ctr0[%lX] ctr1[%lX] ctr2 [%lX] ctr3 [%lX]\n", ctr0, ctr1, ctr2,
ctr3);
+
+ /* Stop the test mode */
+ outb(0x01, probe_ent->port[0].bmdma_addr + 0x01);
+ scr1 = inb(probe_ent->port[0].bmdma_addr + 0x03);
+ PDPRINTK("scr1[%X]\n", scr1);
+ outb(scr1 & 0xBF, probe_ent->port[0].bmdma_addr + 0x03);
+
+ /* calculate the input clock in Hz */
+ pll_clock = (long) ((start_count - end_count) * 1000);
+
+ PDPRINTK("start[%lu] end[%lu] \n", start_count, end_count);
+ PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock);
+
+ return pll_clock;
+}
+/**
+ * pdc_hardware_init - Initialize the hardware.
+ * @pdev: instance of pci_dev found
+ * @pdc_controller: controller specific information
+ * @pe: for the port address
+ */
+static int pdc_hardware_init(struct pci_dev *pdev, struct
pdc_pata_ide_controller* pdc_controller, struct ata_probe_ent *pe)
+{
+ long pll_clock;
+
+ /* Enable the ROM */
+ if (pdev->resource[PCI_ROM_RESOURCE].start) {
+ pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
+ pdev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ printk(KERN_INFO DRV_NAME ": ROM enabled at 0x%08lx\n",
+ pdev->resource[PCI_ROM_RESOURCE].start);
+ }
+
+ /*
+ * Determine the PLL input clock rate.
+ * On some system, where PCI bus is running at non-standard clock rate.
+ * Ex. 25MHz or 40MHz, we have to adjust the cycle_time.
+ * The pdc20275 controller employs PLL circuit to help correct timing
registers setting.
+ */
+
+ /* Detect PLL input clock rate */
+ pll_clock = detect_pll_input_clock(pe);
+
+ if(pll_clock < 0) /* counter overflow? Try again. */
+ pll_clock = detect_pll_input_clock(pe);
+
+ printk(KERN_INFO DRV_NAME ": PLL input clock %ld kHz\n", pll_clock/1000);
+
+ /* Adjust PLL control register */
+ adjust_pll(pdc_controller, pe, pll_clock);
+
+ return 0;
+}
+/**
+ * pdc_new_init_one - PCI probe function
+ * Called when an instance of PCI adapter is inserted.
+ * This function checks whether the hardware is supported,
+ * initialize hardware and register an instance of ata_host_set to
+ * libata by providing struct ata_probe_ent and ata_device_add().
+ * (implements struct pci_driver.probe() )
+ *
+ * @pdev: instance of pci_dev found
+ * @ent: matching entry in the id_tbl[]
+ */
+static int __devinit pdc_new_init_one(struct pci_dev *pdev, const struct
pci_device_id *ent)
+{
+ static int printed_version;
+ struct ata_probe_ent *probe_ent = NULL;
+ unsigned int board_idx = (unsigned int) ent->driver_data;
+ struct pdc_pata_ide_controller* pdc_controller = &
(pdc_pata_controller_tbl[board_idx]);
+ int rc;
+
+ if (!printed_version++)
+ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+ printk(KERN_INFO DRV_NAME ": Promise %s ATA/%lu controller\n",
+ pdc_controller->chip_name,
+ pdc_controller->pll_pout_required/1000000);
+
+ /*
+ * FIXME: Skip Promise PDC20276 attached to I2O RAID controller
+ */
+
+ /*
+ * FIXME: Special handling for Promise PDC20270 attached to DEC DC21150
PCI south bridge.
+ */
+
+ /*
+ * FIXME: If this driver happens to only be useful on Apple's K2, then
+ * we should check that here as it has a normal Serverworks ID
+ */
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out;
+
+ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+ if (rc)
+ goto err_out_regions;
+
+ rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+ if (rc)
+ goto err_out_regions;
+
+ /* Prepare the probe entry */
+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ if (probe_ent == NULL) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ memset(probe_ent, 0, sizeof(*probe_ent));
+ probe_ent->pdev = pdev;
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ probe_ent->sht = pdc_new_port_info[pdc_controller->max_udma_mode].sht;
+ probe_ent->host_flags =
pdc_new_port_info[pdc_controller->max_udma_mode].host_flags;
+ probe_ent->pio_mask =
pdc_new_port_info[pdc_controller->max_udma_mode].pio_mask;
+ probe_ent->udma_mask =
pdc_new_port_info[pdc_controller->max_udma_mode].udma_mask;
+ probe_ent->port_ops =
pdc_new_port_info[pdc_controller->max_udma_mode].port_ops;
+
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+
+ probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+ ata_std_ports(&probe_ent->port[0]);
+ probe_ent->port[0].altstatus_addr =
+ probe_ent->port[0].ctl_addr =
+ pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+ probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
+ probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+ ata_std_ports(&probe_ent->port[1]);
+ probe_ent->port[1].altstatus_addr =
+ probe_ent->port[1].ctl_addr =
+ pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+ probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+
+ probe_ent->n_ports = 2;
+
+ pci_set_master(pdev);
+ //pci_enable_intx(pdev);
+
+ /* initialize adapter */
+ if(pdc_hardware_init(pdev, pdc_controller, probe_ent) != 0)
+ goto err_out_free_ent;
+
+ /* FIXME: check ata_device_add return value */
+ ata_device_add(probe_ent);
+ kfree(probe_ent);
+
+ return 0;
+
+err_out_free_ent:
+ kfree(probe_ent);
+err_out_regions:
+ pci_release_regions(pdev);
+err_out:
+ pci_disable_device(pdev);
+ return rc;
+}
+/**
+ * pdc_new_remove_one - Called to remove a single instance of the
+ * adapter.
+ *
+ * @dev: The PCI device to remove.
+ * FIXME: module load/unload not working yet
+ */
+static void __devexit pdc_new_remove_one(struct pci_dev *pdev)
+{
+ ata_pci_remove_one(pdev);
+}
+/**
+ * pdc_new_init - Called after this module is loaded into the kernel.
+ */
+static int __init pdc_new_init(void)
+{
+ return pci_module_init(&pdc_new_pci_driver);
+}
+/**
+ * pdc_new_exit - Called before this module unloaded from the kernel
+ */
+static void __exit pdc_new_exit(void)
+{
+ pci_unregister_driver(&pdc_new_pci_driver);
+}
+
+module_init(pdc_new_init);
+module_exit(pdc_new_exit);
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-13 10:06 [PATCH/RFC] Port of pdc202xx_new driver to libata Albert Lee @ 2004-10-13 19:32 ` Bartlomiej Zolnierkiewicz 2004-10-13 19:58 ` Jeff Garzik 0 siblings, 1 reply; 11+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2004-10-13 19:32 UTC (permalink / raw) To: Albert Lee; +Cc: Jeff Garzik, IDE Linux On Wed, 13 Oct 2004 18:06:19 +0800, Albert Lee <albertcc@tw.ibm.com> wrote: > Hi, Jeff and Bart: Hi! > I am trying to port the Promise pdc202xx_new driver to libata and adding > the > PLL tuning code to it. (The motivation is hotplug of the Promise host > adapter.) I have libata version of pdc202xx_new for a long time now but this one looks superior as it handles PLL. :-) > The ported driver has been tested with pdc20269 and pdc20275 on i386 and > x86_64 boxes, with 33 MHz PCI bus and 66 MHz PCI bus respectively. > It seems to be working fine with harddisk drives. > (However, CD-ROM drives not working yet, even when > ATA_ENABLE_PATA and ATA_ENABLE_ATAPI are enabled.) Somehow this doesn't surprise me... > My question is, in the current kernel, the IDE subsystem drives PATA chips > and libata drives SATA chips. Will PATA driver like this be accepted into > libata? My opinion is: yes but not now, final answer is of course left to Jeff. > Thanks, > > Albert Lee > (The patch is against 2.6.8.1.) It seems your mail client screwed it. I will try to comment on the patch anyway... > ******************************************************************** > diff -Nru linux-2.6.8.1/drivers/scsi/Kconfig > linux-2.6.8.1-mod/drivers/scsi/Kconfig > --- linux-2.6.8.1/drivers/scsi/Kconfig 2004-08-14 18:56:14.000000000 +0800 > +++ linux-2.6.8.1-mod/drivers/scsi/Kconfig 2004-10-13 15:38:23.000000000 > +0800 > @@ -441,6 +441,14 @@ > > If unsure, say N. > > +config SCSI_PATA_PDC_NEW > + tristate "Promise PATA 202xx new support" > + depends on SCSI_SATA && PCI > + help > + This option enables support for Promise PATA pdc20268 to pdc20277 Host > Adapters. > + > + If unsure, say N. > + > config SCSI_SATA_PROMISE > tristate "Promise SATA TX2/TX4 support" > depends on SCSI_SATA && PCI > diff -Nru linux-2.6.8.1/drivers/scsi/Makefile > linux-2.6.8.1-mod/drivers/scsi/Makefile > --- linux-2.6.8.1/drivers/scsi/Makefile 2004-08-14 18:55:59.000000000 +0800 > +++ linux-2.6.8.1-mod/drivers/scsi/Makefile 2004-10-13 15:38:26.000000000 > +0800 > @@ -121,6 +121,7 @@ > obj-$(CONFIG_SCSI_IPR) += ipr.o > obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o > obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o > +obj-$(CONFIG_SCSI_PATA_PDC_NEW) += libata.o pata_pdc202xx_new.o why not jus pata_pdc_new? or pata_pdc_27x? > obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o > obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o > obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o > diff -Nru linux-2.6.8.1/drivers/scsi/pata_pdc202xx_new.c > linux-2.6.8.1-mod/drivers/scsi/pata_pdc202xx_new.c > --- linux-2.6.8.1/drivers/scsi/pata_pdc202xx_new.c 1970-01-01 > 08:00:00.000000000 +0800 > +++ linux-2.6.8.1-mod/drivers/scsi/pata_pdc202xx_new.c 2004-10-13 > 16:52:11.000000000 +0800 > @@ -0,0 +1,721 @@ > +/* > + * Promise PATA TX2/TX4/TX2000/133 IDE driver for pdc20268 to pdc20277. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version > + * 2 of the License, or (at your option) any later version. > + * > + * Ported to libata by: > + * Albert Lee <albertcc@tw.ibm.com> IBM Corporation > + * > + * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> > + * Portions Copyright (C) 1999 Promise Technology, Inc. > + * > + * Author: Frank Tiernan (frankt@promise.com) > + * Released under terms of General Public License > + * > + * > + */ > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/pci.h> > +#include <linux/init.h> > +#include <linux/blkdev.h> > +#include <linux/delay.h> > +#include "scsi.h" > +#include <scsi/scsi_host.h> > +#include <linux/libata.h> > +#include <asm/io.h> > + > +#define DRV_NAME "pata_pdc202xx_new" > +#define DRV_VERSION "0.50" > +#undef PDC_DEBUG > + > +#ifdef PDC_DEBUG > +#define PDPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, > ## args) > +#else > +#define PDPRINTK(fmt, args...) > +#endif > + > +enum { > + PDC_UDMA_100 = 0, > + PDC_UDMA_133 = 1, > + > + PDC_100_MHZ = 100000000, > + PDC_133_MHZ = 133333333, > +}; > + > +static int pdc_new_init_one(struct pci_dev *pdev, const struct > pci_device_id *ent); > +static void pdc_new_remove_one(struct pci_dev *pdev); > +static void pdc_new_phy_reset(struct ata_port *ap); > +static void pdc_new_set_piomode(struct ata_port *ap, struct ata_device > *adev, unsigned int pio); > +static void pdc_new_set_udmamode(struct ata_port *ap, struct ata_device > *adev, unsigned int udma); > + > +static struct pdc_pata_ide_controller { > + char* chip_name; > + int max_udma_mode; > + long pll_pout_required; > +} pdc_pata_controller_tbl [] = { > + { "Ultra100 TX2", PDC_UDMA_100, PDC_100_MHZ }, /* pdc20268 */ > + { "Ultra133 TX2", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20269 */ > + { "FastTrak LP/TX2/TX4", PDC_UDMA_100, PDC_100_MHZ }, /* pdc20270 */ > + { "FastTrak TX2000", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20271 */ > + { "MBUltra133", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20275 */ > + { "MBFastTrak 133 Lite", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20276 */ > + { "SBFastTrak 133 Lite", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20277 */ > +}; This table is redundant: * official names (more detailed) can be get from lspci * PDC_UDMA_[100,133] implies PDC_[100,133]_MHZ * max UDMA rate is available from ata_port_info etc. > +static struct pci_device_id pdc_new_pci_tbl[] = { > +#ifdef ATA_ENABLE_PATA > + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, > PCI_ANY_ID, 0, 0, 0 }, > + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, > PCI_ANY_ID, 0, 0, 1 }, > + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, > PCI_ANY_ID, 0, 0, 2 }, > + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, > PCI_ANY_ID, 0, 0, 3 }, > + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, > PCI_ANY_ID, 0, 0, 4 }, > + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, > PCI_ANY_ID, 0, 0, 5 }, > + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, > PCI_ANY_ID, 0, 0, 6 }, > +#endif > + { } /* terminate list */ > +}; > + > +static struct pci_driver pdc_new_pci_driver = { > + .name = DRV_NAME, > + .id_table = pdc_new_pci_tbl, > + .probe = pdc_new_init_one, > + .remove = __devexit_p(pdc_new_remove_one), > +}; > + > +static Scsi_Host_Template pdc_new_sht = { > + .module = THIS_MODULE, > + .name = DRV_NAME, > + .queuecommand = ata_scsi_queuecmd, > + .eh_strategy_handler = ata_scsi_error, > + .can_queue = ATA_DEF_QUEUE, > + .this_id = ATA_SHT_THIS_ID, > + .sg_tablesize = LIBATA_MAX_PRD, > + .max_sectors = ATA_MAX_SECTORS, > + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, > + .emulated = ATA_SHT_EMULATED, > + .use_clustering = ATA_SHT_USE_CLUSTERING, > + .proc_name = DRV_NAME, > + .dma_boundary = ATA_DMA_BOUNDARY, > + .slave_configure = ata_scsi_slave_config, > + .bios_param = ata_std_bios_param, > +}; > + > +static struct ata_port_operations pdc_new_pata_ops = { > + .port_disable = ata_port_disable, > + .set_piomode = pdc_new_set_piomode, > + .set_udmamode = pdc_new_set_udmamode, > + > + .tf_load = ata_tf_load_pio, > + .tf_read = ata_tf_read_pio, > + .exec_command = ata_exec_command_pio, > + .check_status = ata_check_status_pio, > + > + .phy_reset = pdc_new_phy_reset, > + > + .bmdma_setup = ata_bmdma_setup_pio, > + .bmdma_start = ata_bmdma_start_pio, > + //.fill_sg = ata_fill_sg, > + .qc_prep = ata_qc_prep, > + .qc_issue = ata_qc_issue_prot, > + .eng_timeout = ata_eng_timeout, > + > + .irq_handler = ata_interrupt, > + .irq_clear = ata_bmdma_irq_clear, > + > + .port_start = ata_port_start, > + .port_stop = ata_port_stop, > +}; > + > +static struct ata_port_info pdc_new_port_info[] = { > + /* PDC_UDMA_100 */ > + { > + .sht = &pdc_new_sht, > + .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | > + ATA_FLAG_SRST, /* | ATA_FLAG_MMIO, */ > + .pio_mask = 0x03, /* pio3-4 */ > + .udma_mask = ATA_UDMA5, > + .port_ops = &pdc_new_pata_ops, > + }, > + /* PDC_UDMA_133 */ > + { > + .sht = &pdc_new_sht, > + .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | > + ATA_FLAG_SRST, > + .pio_mask = 0x03, /* pio3-4 */ > + .udma_mask = ATA_UDMA6, > + .port_ops = &pdc_new_pata_ops, > + }, > +}; > + > +MODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Albert Lee"); > +MODULE_DESCRIPTION("libata driver module for Promise PDC20268 to > PDC20277"); > +MODULE_LICENSE("GPL"); > +MODULE_DEVICE_TABLE(pci, pdc_new_pci_tbl); > + > +/** > + * pdc_get_indexed_reg - Set pdc202xx extended register > + * @ap: Port to which the extended register is set > + * @index: index of the extended register > + */ > +static u8 pdc_get_indexed_reg(struct ata_port *ap, u8 index) > +{ > + u8 tmp8; > + > + outb(index, ap->ioaddr.bmdma_addr + 1); > + tmp8 = inb(ap->ioaddr.bmdma_addr + 3); > + > + PDPRINTK("Get index reg%X[%X] \n", index, tmp8); > + return tmp8; > +} > +/** > + * pdc_set_indexed_reg - Read pdc202xx extended register > + * @ap: Port to which the extended register is read > + * @index: index of the extended register > + */ > +static void pdc_set_indexed_reg(struct ata_port *ap, u8 index, u8 value) > +{ > + outb(index, ap->ioaddr.bmdma_addr + 1); > + outb(value, ap->ioaddr.bmdma_addr + 3); > + PDPRINTK("Set index reg%X[%X] \n", index, value); > +} > +/** > + * pdc_set_pio - Set the PIO extended registers > + * @ap: Port to which the extended register is set > + * @adev: Device to set > + * @value0: value for extended register at 0x0c > + * @value1: value for extended register at 0x0d > + * @value2: value for extended register at 0x13 > + */ > +static void pdc_set_pio(struct ata_port *ap, struct ata_device *adev, u8 > value0, u8 value1, u8 value2) > +{ > + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; > + u8 adj = (drive_dn%2) ? 0x08 : 0x00; > + > + PDPRINTK("Set pio regs... \n"); > + > + pdc_set_indexed_reg(ap, 0x0c + adj, value0); > + pdc_set_indexed_reg(ap, 0x0d + adj, value1); > + pdc_set_indexed_reg(ap, 0x13 + adj, value2); > + > + PDPRINTK("Set pio regs done\n"); > +} > +/** > + * pdc_set_ultra - Set the UDMA extended registers > + * @ap: Port to which the extended register is set > + * @adev: Device to set > + * @value0: value for extended register at 0x10 > + * @value1: value for extended register at 0x11 > + * @value2: value for extended register at 0x12 > + */ > +static void pdc_set_ultra(struct ata_port *ap, struct ata_device *adev, u8 > value0, u8 value1, u8 value2) > +{ > + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; > + u8 adj = (drive_dn%2) ? 0x08 : 0x00; > + > + PDPRINTK("Set udma regs... \n"); > + pdc_set_indexed_reg(ap, 0x10 + adj, value0); > + pdc_set_indexed_reg(ap, 0x11 + adj, value1); > + pdc_set_indexed_reg(ap, 0x12 + adj, value2); > + > + PDPRINTK("Set udma regs done\n"); > +} > +/** > + * pdc_new_pata_cbl_detect - Probe host controller cable detect info > + * @ap: Port for which cable detect info is desired > + * > + * Read 80c cable indicator from Promise extended register. > + * This register is normally set by firmware. > + * > + * LOCKING: > + * None (inherited from caller). > + */ > +static void pdc_new_cbl_detect(struct ata_port *ap) > +{ > + u8 cbl40c; > + > + /* For UDMA33, no 80c support is required */ > + if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0) > + goto cbl40; this can't happen > + /* check cable detect results */ > + cbl40c = pdc_get_indexed_reg(ap, 0x0b) & 0x04; > + > + if (cbl40c) > + goto cbl40; > + > + PDPRINTK("No cable or 80-conductor cable on port %d\n", ap->port_no); > + > + ap->cbl = ATA_CBL_PATA80; > + return; > + > +cbl40: > + printk(KERN_INFO DRV_NAME ": 40-conductor cable detected on port %d\n", > ap->port_no); > + ap->cbl = ATA_CBL_PATA40; > + ap->udma_mask &= ATA_UDMA_MASK_40C; > +} > +/** > + * pdc_new_port_enabled - Check extended register at 0x04 to see whether > the port is enabled. > + * @ap: Port to check > + */ > +static inline int pdc_new_port_enabled(struct ata_port *ap) > +{ > + return pdc_get_indexed_reg(ap, 0x04) & 0x02; > +} > +/** > + * pdc_new_phy_reset - Probe specified port on PATA host controller > + * @ap: Port to probe > + * > + * Probe PATA phy. > + * > + * LOCKING: > + * None (inherited from caller). > + */ > +static void pdc_new_phy_reset(struct ata_port *ap) > +{ > + /* Check whether port enabled */ > + if (!pdc_new_port_enabled(ap)) { > + ata_port_disable(ap); > + printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); > + return; > + } > + > + pdc_new_cbl_detect(ap); > + ata_port_probe(ap); > + ata_bus_reset(ap); > +} > +/** > + * pdc_new_set_piomode - Initialize host controller PATA PIO timings > + * @ap: Port to configure > + * @adev: um > + * @pio: PIO mode, 0 - 4 > + * > + * Set PIO mode for device. > + * > + * LOCKING: > + * None (inherited from caller). > + */ > +static void pdc_new_set_piomode(struct ata_port *ap, struct ata_device > *adev, unsigned int pio) > +{ > + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; > + u8 adj = (drive_dn%2) ? 0x08 : 0x00; > + u8 tmp8; > + > + switch (pio | 0x08) { > + case XFER_PIO_4: > + pdc_set_pio(ap, adev, 0x23, 0x09, 0x25); /* IORDY on, Prefetch off */ > + break; > + case XFER_PIO_3: > + pdc_set_pio(ap, adev, 0x27, 0x0d, 0x35); /* IORDY on, Prefetch off */ > + break; > + //case XFER_PIO_2: pdc_set_pio(ap, adev, 0x23, 0x26, 0x64); break; > + //case XFER_PIO_1: pdc_set_pio(ap, adev, 0x46, 0x29, 0xa4); break; > + //case XFER_PIO_0: pdc_set_pio(ap, adev, 0xfb, 0x2b, 0xac); break; > + default: > + printk(KERN_ERR DRV_NAME ": Unknown pio mode [%d] ignored\n", pio); > + return; > + } pds_set_pio() should be called only once > + /* > + * Check whether the device supports turning off IORDY. > + * For PIO3 and above, the device must support IORDY and set bit 10 > + */ > + if (adev->id[49] & 0x400) { > + /* IORDY_EN & PREFETCH_EN */ > + /* Turn on Prefetch */ > + tmp8 = pdc_get_indexed_reg(ap, 0x13 + adj); > + pdc_set_indexed_reg(ap, 0x13 + adj, tmp8 | 0x03); > + > + PDPRINTK("Turn on prefetch\n"); > + } > + > + printk(KERN_INFO DRV_NAME ": Set to pio mode[%u] \n", pio); > +} > +/** > + * pdc_new_set_udmamode - Initialize host controller PATA UDMA timings > + * @ap: Port to configure > + * @adev: um > + * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6 > + * > + * Set UDMA mode for device. > + * > + * LOCKING: > + * None (inherited from caller). > + */ > +static void pdc_new_set_udmamode(struct ata_port *ap, struct ata_device > *adev, unsigned int udma) > +{ > + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; > + > + u8 adj = (drive_dn%2) ? 0x08 : 0x00; > + u8 tmp8; > + > + if (udma == XFER_UDMA_2) { > + /* > + * Turn off tHOLD. > + * If tHOLD is '1', the hardware will add half clock for data hold time. > + * This code segment seems to be no effect. tHOLD will be overwritten > below. > + */ > + tmp8 = pdc_get_indexed_reg(ap, 0x10 + adj); > + pdc_set_indexed_reg(ap, 0x10 + adj, tmp8 & 0x7f); > + } > + > + switch (udma) { > + case XFER_UDMA_7: > + udma = XFER_UDMA_6; > + case XFER_UDMA_6: pdc_set_ultra(ap, adev, 0x1a, 0x01, 0xcb); break; > + case XFER_UDMA_5: pdc_set_ultra(ap, adev, 0x1a, 0x02, 0xcb); break; > + case XFER_UDMA_4: pdc_set_ultra(ap, adev, 0x1a, 0x03, 0xcd); break; > + case XFER_UDMA_3: pdc_set_ultra(ap, adev, 0x1a, 0x05, 0xcd); break; > + case XFER_UDMA_2: pdc_set_ultra(ap, adev, 0x2a, 0x07, 0xcd); break; > + case XFER_UDMA_1: pdc_set_ultra(ap, adev, 0x3a, 0x0a, 0xd0); break; > + case XFER_UDMA_0: pdc_set_ultra(ap, adev, 0x4a, 0x0f, 0xd5); break; > + default: pdc_set_ultra() should be called only once > + printk(KERN_ERR DRV_NAME ": Unknown udma mode [%u] ignored\n", udma & > 0x07); > + return; > + } > + > + printk(KERN_INFO DRV_NAME ": Set to udma mode[%u] \n", udma & 0x07); > +} > +/** > + * adjust_pll - Adjust the PLL input clock in Hz. > + * > + * @pdc_controller: controller specific information > + * @probe_ent: For the port address > + * @pll_clock: The input of PLL in HZ > + */ > +static void adjust_pll(struct pdc_pata_ide_controller* pdc_controller, > struct ata_probe_ent *probe_ent, long pll_clock) > +{ > + > + u8 pll_ctl0, pll_ctl1; > + long pll_clock_khz = pll_clock / 1000; > + long pout_required = pdc_controller->pll_pout_required; > + long ratio = pout_required / pll_clock_khz; > + int F, R; > + > + /* Sanity check */ > + if (unlikely(pll_clock_khz < 5000L || pll_clock_khz > 70000L)) { > + printk(KERN_ERR DRV_NAME ": Invalid PLL input clock %ldkHz, give up!\n", > pll_clock_khz); > + return; > + } > + > +#ifdef PDC_DEBUG > + /* Show the current clock value of PLL control register > + * (maybe already configured by the firmware) > + */ > + outb(0x02, probe_ent->port[1].bmdma_addr + 0x01); > + pll_ctl0 = inb(probe_ent->port[1].bmdma_addr + 0x03); > + outb(0x03, probe_ent->port[1].bmdma_addr + 0x01); > + pll_ctl1 = inb(probe_ent->port[1].bmdma_addr + 0x03); > + > + printk(KERN_DEBUG DRV_NAME ": pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1); > +#endif > + > + /* > + * Calculate the ratio of F, R and OD > + * POUT = (F + 2) / (( R + 2) * NO) > + */ > + if (ratio < 8600L) { // 8.6x > + /* Using NO = 0x01, R = 0x0D */ > + R = 0x0d; > + } else if (ratio < 12900L) { // 12.9x > + /* Using NO = 0x01, R = 0x08 */ > + R = 0x08; > + } else if (ratio < 16100L) { // 16.1x > + /* Using NO = 0x01, R = 0x06 */ > + R = 0x06; > + } else if (ratio < 64000L) { // 64x > + R = 0x00; > + } else { > + /* Invalid ratio */ > + printk(KERN_ERR DRV_NAME ": Invalid ratio %ld, give up!\n", ratio); > + return; > + } > + > + F = (ratio * (R+2)) / 1000 - 2; > + > + if (unlikely(F < 0 || F > 127)) { > + /* Invalid F */ > + printk(KERN_ERR DRV_NAME ": F[%d] invalid!\n", F); > + return; > + } > + > + PDPRINTK("F[%d] R[%d] ratio*1000[%ld]\n", F, R, ratio); > + > + pll_ctl0 = (u8) F; > + pll_ctl1 = (u8) R; > + > + PDPRINTK("Writing pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1); > + > + outb(0x02, probe_ent->port[1].bmdma_addr + 0x01); > + outb(pll_ctl0, probe_ent->port[1].bmdma_addr + 0x03); > + outb(0x03, probe_ent->port[1].bmdma_addr + 0x01); > + outb(pll_ctl1, probe_ent->port[1].bmdma_addr + 0x03); > + > + /* Wait the PLL circuit to be stable */ > + mdelay(30); > + > +#ifdef PDC_DEBUG > + /* > + * Show the current clock value of PLL control register > + * (maybe configured by the firmware) > + */ > + outb(0x02, probe_ent->port[1].bmdma_addr + 0x01); > + pll_ctl0 = inb(probe_ent->port[1].bmdma_addr + 0x03); > + outb(0x03, probe_ent->port[1].bmdma_addr + 0x01); > + pll_ctl1 = inb(probe_ent->port[1].bmdma_addr + 0x03); > + > + printk(KERN_DEBUG DRV_NAME ": pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1); > +#endif > + > + return; > +} > +/** > + * detect_pll_input_clock - Detect the PLL input clock in Hz. > + * @probe_ent: for the port address > + * Ex. 16949000 on 33MHz PCI bus for pdc20275. > + * Half of the PCI clock. > + */ > +static long detect_pll_input_clock(struct ata_probe_ent *probe_ent) > +{ > + u8 scr1; > + unsigned long ctr0; > + unsigned long ctr1; > + unsigned long ctr2 = 0; > + unsigned long ctr3 = 0; > + > + unsigned long start_count, end_count; > + long pll_clock; > + > + /* Read current counter value */ > + outb(0x20, probe_ent->port[0].bmdma_addr + 0x01); > + ctr0 = inb(probe_ent->port[0].bmdma_addr + 0x03); > + outb(0x21, probe_ent->port[0].bmdma_addr + 0x01); > + ctr1 = inb(probe_ent->port[0].bmdma_addr + 0x03); > + > + outb(0x20, probe_ent->port[1].bmdma_addr + 0x01); > + ctr2 = inb(probe_ent->port[1].bmdma_addr + 0x03); > + outb(0x21, probe_ent->port[1].bmdma_addr + 0x01); > + ctr3 = inb(probe_ent->port[1].bmdma_addr + 0x03); > + > + start_count = (ctr3 << 23 ) | (ctr2 << 15) | (ctr1 << 8) | ctr0; > + > + PDPRINTK("ctr0[%lX] ctr1[%lX] ctr2 [%lX] ctr3 [%lX]\n", ctr0, ctr1, ctr2, > ctr3); > + > + /* Start the test mode */ > + outb(0x01, probe_ent->port[0].bmdma_addr + 0x01); > + scr1 = inb(probe_ent->port[0].bmdma_addr + 0x03); > + PDPRINTK("scr1[%X]\n", scr1); > + outb(scr1 | 0x40, probe_ent->port[0].bmdma_addr + 0x03); > + > + /* Let the counter run for 1000 us. */ > + udelay(1000); > + > + /* Read the counter values again */ > + outb(0x20, probe_ent->port[0].bmdma_addr + 0x01); > + ctr0 = inb(probe_ent->port[0].bmdma_addr + 0x03); > + outb(0x21, probe_ent->port[0].bmdma_addr + 0x01); > + ctr1 = inb(probe_ent->port[0].bmdma_addr + 0x03); > + > + outb(0x20, probe_ent->port[1].bmdma_addr + 0x01); > + ctr2 = inb(probe_ent->port[1].bmdma_addr + 0x03); > + outb(0x21, probe_ent->port[1].bmdma_addr + 0x01); > + ctr3 = inb(probe_ent->port[1].bmdma_addr + 0x03); > + > + end_count = (ctr3 << 23 ) | (ctr2 << 15) | (ctr1 << 8) | ctr0; > + > + PDPRINTK("ctr0[%lX] ctr1[%lX] ctr2 [%lX] ctr3 [%lX]\n", ctr0, ctr1, ctr2, > ctr3); > + > + /* Stop the test mode */ > + outb(0x01, probe_ent->port[0].bmdma_addr + 0x01); > + scr1 = inb(probe_ent->port[0].bmdma_addr + 0x03); > + PDPRINTK("scr1[%X]\n", scr1); > + outb(scr1 & 0xBF, probe_ent->port[0].bmdma_addr + 0x03); > + > + /* calculate the input clock in Hz */ > + pll_clock = (long) ((start_count - end_count) * 1000); > + > + PDPRINTK("start[%lu] end[%lu] \n", start_count, end_count); > + PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock); > + > + return pll_clock; > +} > +/** > + * pdc_hardware_init - Initialize the hardware. > + * @pdev: instance of pci_dev found > + * @pdc_controller: controller specific information > + * @pe: for the port address > + */ > +static int pdc_hardware_init(struct pci_dev *pdev, struct > pdc_pata_ide_controller* pdc_controller, struct ata_probe_ent *pe) > +{ > + long pll_clock; > + > + /* Enable the ROM */ > + if (pdev->resource[PCI_ROM_RESOURCE].start) { > + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, > + pdev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); > + printk(KERN_INFO DRV_NAME ": ROM enabled at 0x%08lx\n", > + pdev->resource[PCI_ROM_RESOURCE].start); > + } is this really needed? > + /* > + * Determine the PLL input clock rate. > + * On some system, where PCI bus is running at non-standard clock rate. > + * Ex. 25MHz or 40MHz, we have to adjust the cycle_time. > + * The pdc20275 controller employs PLL circuit to help correct timing > registers setting. > + */ > + > + /* Detect PLL input clock rate */ > + pll_clock = detect_pll_input_clock(pe); > + > + if(pll_clock < 0) /* counter overflow? Try again. */ > + pll_clock = detect_pll_input_clock(pe); > + > + printk(KERN_INFO DRV_NAME ": PLL input clock %ld kHz\n", pll_clock/1000); > + > + /* Adjust PLL control register */ > + adjust_pll(pdc_controller, pe, pll_clock); > + > + return 0; > +} > +/** > + * pdc_new_init_one - PCI probe function > + * Called when an instance of PCI adapter is inserted. > + * This function checks whether the hardware is supported, > + * initialize hardware and register an instance of ata_host_set to > + * libata by providing struct ata_probe_ent and ata_device_add(). > + * (implements struct pci_driver.probe() ) > + * > + * @pdev: instance of pci_dev found > + * @ent: matching entry in the id_tbl[] > + */ > +static int __devinit pdc_new_init_one(struct pci_dev *pdev, const struct > pci_device_id *ent) > +{ > + static int printed_version; > + struct ata_probe_ent *probe_ent = NULL; > + unsigned int board_idx = (unsigned int) ent->driver_data; > + struct pdc_pata_ide_controller* pdc_controller = & > (pdc_pata_controller_tbl[board_idx]); > + int rc; > + > + if (!printed_version++) > + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); > + > + printk(KERN_INFO DRV_NAME ": Promise %s ATA/%lu controller\n", > + pdc_controller->chip_name, > + pdc_controller->pll_pout_required/1000000); > + > + /* > + * FIXME: Skip Promise PDC20276 attached to I2O RAID controller > + */ > + > + /* > + * FIXME: Special handling for Promise PDC20270 attached to DEC DC21150 > PCI south bridge. > + */ > + > + /* > + * FIXME: If this driver happens to only be useful on Apple's K2, then > + * we should check that here as it has a normal Serverworks ID > + */ cut'n'paste mistake > + rc = pci_enable_device(pdev); > + if (rc) > + return rc; > + > + rc = pci_request_regions(pdev, DRV_NAME); > + if (rc) > + goto err_out; > + > + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); > + if (rc) > + goto err_out_regions; > + > + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); > + if (rc) > + goto err_out_regions; > + > + /* Prepare the probe entry */ > + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); > + if (probe_ent == NULL) { > + rc = -ENOMEM; > + goto err_out_regions; > + } > + > + memset(probe_ent, 0, sizeof(*probe_ent)); > + probe_ent->pdev = pdev; > + INIT_LIST_HEAD(&probe_ent->node); > + > + probe_ent->sht = pdc_new_port_info[pdc_controller->max_udma_mode].sht; > + probe_ent->host_flags = > pdc_new_port_info[pdc_controller->max_udma_mode].host_flags; > + probe_ent->pio_mask = > pdc_new_port_info[pdc_controller->max_udma_mode].pio_mask; > + probe_ent->udma_mask = > pdc_new_port_info[pdc_controller->max_udma_mode].udma_mask; > + probe_ent->port_ops = > pdc_new_port_info[pdc_controller->max_udma_mode].port_ops; > + > + probe_ent->irq = pdev->irq; > + probe_ent->irq_flags = SA_SHIRQ; > + > + probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); > + ata_std_ports(&probe_ent->port[0]); > + probe_ent->port[0].altstatus_addr = > + probe_ent->port[0].ctl_addr = > + pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; > + probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); > + > + probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); > + ata_std_ports(&probe_ent->port[1]); > + probe_ent->port[1].altstatus_addr = > + probe_ent->port[1].ctl_addr = > + pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; > + probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; > + > + probe_ent->n_ports = 2; > + > + pci_set_master(pdev); > + //pci_enable_intx(pdev); > + > + /* initialize adapter */ > + if(pdc_hardware_init(pdev, pdc_controller, probe_ent) != 0) > + goto err_out_free_ent; pdc_hardware_init() seems to be the only reason why generic ata_pci_init_one() can't be used here, what about adding sth. like ->init_device() to struct ata_port_info? > + /* FIXME: check ata_device_add return value */ > + ata_device_add(probe_ent); > + kfree(probe_ent); > + > + return 0; > + > +err_out_free_ent: > + kfree(probe_ent); > +err_out_regions: > + pci_release_regions(pdev); > +err_out: > + pci_disable_device(pdev); > + return rc; > +} > +/** > + * pdc_new_remove_one - Called to remove a single instance of the > + * adapter. > + * > + * @dev: The PCI device to remove. > + * FIXME: module load/unload not working yet what exacty (besides PLL support) are the advantages of libata driver? > + */ > +static void __devexit pdc_new_remove_one(struct pci_dev *pdev) > +{ > + ata_pci_remove_one(pdev); > +} > +/** > + * pdc_new_init - Called after this module is loaded into the kernel. > + */ > +static int __init pdc_new_init(void) > +{ > + return pci_module_init(&pdc_new_pci_driver); > +} > +/** > + * pdc_new_exit - Called before this module unloaded from the kernel > + */ > +static void __exit pdc_new_exit(void) > +{ > + pci_unregister_driver(&pdc_new_pci_driver); > +} > + > +module_init(pdc_new_init); > +module_exit(pdc_new_exit); > > Thanks. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-13 19:32 ` Bartlomiej Zolnierkiewicz @ 2004-10-13 19:58 ` Jeff Garzik 2004-10-13 20:16 ` Bartlomiej Zolnierkiewicz 2004-10-18 10:30 ` Albert Lee 0 siblings, 2 replies; 11+ messages in thread From: Jeff Garzik @ 2004-10-13 19:58 UTC (permalink / raw) To: Bartlomiej Zolnierkiewicz, Albert Lee; +Cc: IDE Linux I'll use this message to respond to both Albert and you (Bart). Bartlomiej Zolnierkiewicz wrote: > On Wed, 13 Oct 2004 18:06:19 +0800, Albert Lee <albertcc@tw.ibm.com> wrote: > >>Hi, Jeff and Bart: > > > Hi! > > >> I am trying to port the Promise pdc202xx_new driver to libata and adding >>the >>PLL tuning code to it. (The motivation is hotplug of the Promise host >>adapter.) > > > I have libata version of pdc202xx_new for a long time now > but this one looks superior as it handles PLL. :-) > > >>The ported driver has been tested with pdc20269 and pdc20275 on i386 and >>x86_64 boxes, with 33 MHz PCI bus and 66 MHz PCI bus respectively. >>It seems to be working fine with harddisk drives. I got a report that sata_promise has problems in some >=66Mhz configurations, but works fine with 33Mhz configuration. I bet I could learn a few things from this driver too, as the concepts probably apply to newer hardware. >>(However, CD-ROM drives not working yet, even when >>ATA_ENABLE_PATA and ATA_ENABLE_ATAPI are enabled.) > > > Somehow this doesn't surprise me... hehe :) >>My question is, in the current kernel, the IDE subsystem drives PATA chips >>and libata drives SATA chips. Will PATA driver like this be accepted into >>libata? > > > My opinion is: yes but not now, final answer is of course left to Jeff. With the progress currently being made, I think my preference would be to start collecting PATA drivers such this in my libata-dev queue. I would not send these PATA drivers upstream until the PATA to-do items are complete (see other email), but it would be nice to have a central location (both BK and patch on kernel.org) for developers and users to mess with PATA support. So, send PATA drivers to me and I will merge... but please understand that I will not send upstream for quite some time. >>Albert Lee >>(The patch is against 2.6.8.1.) > > > It seems your mail client screwed it. > > I will try to comment on the patch anyway... I agree with Bart's comments on the patch. It was also mangled here. Albert, if you would resend a patch with Bart's fixes, I'll merge into libata-dev. My own comments: >> obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o >>> +obj-$(CONFIG_SCSI_PATA_PDC_NEW) += libata.o pata_pdc202xx_new.o > > > why not jus pata_pdc_new? or pata_pdc_27x? I would prefer to eliminate the "_new" suffix. Other than that I don't really care. If I had written the driver, I would have named it pata_pdc202xx I suppose. > +} pdc_pata_controller_tbl [] = { >> + { "Ultra100 TX2", PDC_UDMA_100, PDC_100_MHZ }, /* pdc20268 */ >> + { "Ultra133 TX2", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20269 */ >> + { "FastTrak LP/TX2/TX4", PDC_UDMA_100, PDC_100_MHZ }, /* pdc20270 */ >> + { "FastTrak TX2000", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20271 */ >> + { "MBUltra133", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20275 */ >> + { "MBFastTrak 133 Lite", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20276 */ >> + { "SBFastTrak 133 Lite", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20277 */ >> +}; In general I prefer to eliminate _all_ "marketing strings" from all drivers. Model names appear on the market far faster than any maintainer could hope to keep up. (granted, this is old hardware and not changing, in this case) So as a general rule, it is preferred to only use strings when absolutely necessary, eliminating them completely if at all possible. > what exacty (besides PLL support) are the advantages > of libata driver? IDE controller hotplug is a lot easier, and proper locking is already there :) Jeff ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-13 19:58 ` Jeff Garzik @ 2004-10-13 20:16 ` Bartlomiej Zolnierkiewicz 2004-10-18 10:30 ` Albert Lee 1 sibling, 0 replies; 11+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2004-10-13 20:16 UTC (permalink / raw) To: Jeff Garzik; +Cc: Albert Lee, IDE Linux On Wed, 13 Oct 2004 15:58:50 -0400, Jeff Garzik <jgarzik@pobox.com> wrote: > >>My question is, in the current kernel, the IDE subsystem drives PATA chips > >>and libata drives SATA chips. Will PATA driver like this be accepted into > >>libata? > > > > > > My opinion is: yes but not now, final answer is of course left to Jeff. > > With the progress currently being made, I think my preference would be > to start collecting PATA drivers such this in my libata-dev queue. > > I would not send these PATA drivers upstream until the PATA to-do items > are complete (see other email), but it would be nice to have a central > location (both BK and patch on kernel.org) for developers and users to > mess with PATA support. I was going to start libata-pata-2.6 (from libata-dev-2.6) but this sounds even better :) and lets ignore /dev/hda vs /dev/sda issue completely for now in hope that udev will fix this for us etc. :) > My own comments: > > >> obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o > >>> +obj-$(CONFIG_SCSI_PATA_PDC_NEW) += libata.o pata_pdc202xx_new.o > > > > > > why not jus pata_pdc_new? or pata_pdc_27x? > > I would prefer to eliminate the "_new" suffix. Other than that I don't > really care. If I had written the driver, I would have named it > pata_pdc202xx I suppose. There is a high chance that somebody will also port pdc202xx_old driver to libata so pata_pdc202xx will be confusing. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-13 19:58 ` Jeff Garzik 2004-10-13 20:16 ` Bartlomiej Zolnierkiewicz @ 2004-10-18 10:30 ` Albert Lee 2004-10-18 17:00 ` Jeff Garzik 1 sibling, 1 reply; 11+ messages in thread From: Albert Lee @ 2004-10-18 10:30 UTC (permalink / raw) To: Jeff Garzik, Bartlomiej Zolnierkiewicz; +Cc: IDE Linux [-- Attachment #1: Type: text/plain, Size: 5822 bytes --] Hi, Jeff and Bart: Thanks for your review and sorry for the late reply. The updated patch is attached for your review/comment. (The patch is against libata-dev-2.6) 1. > why not jus pata_pdc_new? or pata_pdc_27x? changed to "pata_pdc2027x". 2. > This table is redundant: >* official names (more detailed) can be get from lspci >* PDC_UDMA_[100,133] implies PDC_[100,133]_MHZ >* max UDMA rate is available from ata_port_info etc. Fixed. 3. >> + /* For UDMA33, no 80c support is required */ >> + if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0) >> + goto cbl40; > >this can't happen Removed. 4. > pds_set_pio() should be called only once > pdc_set_ultra() should be called only once Fixed. 5. >> + /* Enable the ROM */ >> + if (pdev->resource[PCI_ROM_RESOURCE].start) { >> + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, >> + pdev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); >> + printk(KERN_INFO DRV_NAME ": ROM enabled at 0x%08lx\n", >> + pdev->resource[PCI_ROM_RESOURCE].start); >> + } > is this really needed? Removed. 6. >> + * FIXME: If this driver happens to only be useful on Apple's K2, then >> + * we should check that here as it has a normal Serverworks ID >> + */ > >cut'n'paste mistake Fixed. 7. > pdc_hardware_init() seems to be the only reason > why generic ata_pci_init_one() can't be used here, > what about adding sth. like ->init_device() to > struct ata_port_info? Could this be fixed later? (I am afraid to touch the core. Need more time to study.) Thanks, Albert Lee ----- Original Message ----- From: "Jeff Garzik" <jgarzik@pobox.com> To: "Bartlomiej Zolnierkiewicz" <bzolnier@gmail.com>; "Albert Lee" <albertcc@tw.ibm.com> Cc: "IDE Linux" <linux-ide@vger.kernel.org> Sent: Thursday, October 14, 2004 3:58 AM Subject: Re: [PATCH/RFC] Port of pdc202xx_new driver to libata > > I'll use this message to respond to both Albert and you (Bart). > > Bartlomiej Zolnierkiewicz wrote: > > On Wed, 13 Oct 2004 18:06:19 +0800, Albert Lee <albertcc@tw.ibm.com> wrote: > > > >>Hi, Jeff and Bart: > > > > > > Hi! > > > > > >> I am trying to port the Promise pdc202xx_new driver to libata and adding > >>the > >>PLL tuning code to it. (The motivation is hotplug of the Promise host > >>adapter.) > > > > > > I have libata version of pdc202xx_new for a long time now > > but this one looks superior as it handles PLL. :-) > > > > > >>The ported driver has been tested with pdc20269 and pdc20275 on i386 and > >>x86_64 boxes, with 33 MHz PCI bus and 66 MHz PCI bus respectively. > >>It seems to be working fine with harddisk drives. > > I got a report that sata_promise has problems in some >=66Mhz > configurations, but works fine with 33Mhz configuration. I bet I could > learn a few things from this driver too, as the concepts probably apply > to newer hardware. > > > >>(However, CD-ROM drives not working yet, even when > >>ATA_ENABLE_PATA and ATA_ENABLE_ATAPI are enabled.) > > > > > > Somehow this doesn't surprise me... > > hehe :) > > > >>My question is, in the current kernel, the IDE subsystem drives PATA chips > >>and libata drives SATA chips. Will PATA driver like this be accepted into > >>libata? > > > > > > My opinion is: yes but not now, final answer is of course left to Jeff. > > With the progress currently being made, I think my preference would be > to start collecting PATA drivers such this in my libata-dev queue. > > I would not send these PATA drivers upstream until the PATA to-do items > are complete (see other email), but it would be nice to have a central > location (both BK and patch on kernel.org) for developers and users to > mess with PATA support. > > So, send PATA drivers to me and I will merge... but please understand > that I will not send upstream for quite some time. > > > > >>Albert Lee > >>(The patch is against 2.6.8.1.) > > > > > > It seems your mail client screwed it. > > > > I will try to comment on the patch anyway... > > I agree with Bart's comments on the patch. It was also mangled here. > > Albert, if you would resend a patch with Bart's fixes, I'll merge into > libata-dev. > > My own comments: > > >> obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o > >>> +obj-$(CONFIG_SCSI_PATA_PDC_NEW) += libata.o pata_pdc202xx_new.o > > > > > > why not jus pata_pdc_new? or pata_pdc_27x? > > I would prefer to eliminate the "_new" suffix. Other than that I don't > really care. If I had written the driver, I would have named it > pata_pdc202xx I suppose. > > > > +} pdc_pata_controller_tbl [] = { > >> + { "Ultra100 TX2", PDC_UDMA_100, PDC_100_MHZ }, /* pdc20268 */ > >> + { "Ultra133 TX2", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20269 */ > >> + { "FastTrak LP/TX2/TX4", PDC_UDMA_100, PDC_100_MHZ }, /* pdc20270 */ > >> + { "FastTrak TX2000", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20271 */ > >> + { "MBUltra133", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20275 */ > >> + { "MBFastTrak 133 Lite", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20276 */ > >> + { "SBFastTrak 133 Lite", PDC_UDMA_133, PDC_133_MHZ }, /* pdc20277 */ > >> +}; > > In general I prefer to eliminate _all_ "marketing strings" from all > drivers. Model names appear on the market far faster than any > maintainer could hope to keep up. (granted, this is old hardware and > not changing, in this case) So as a general rule, it is preferred to > only use strings when absolutely necessary, eliminating them completely > if at all possible. > > > what exacty (besides PLL support) are the advantages > > of libata driver? > > IDE controller hotplug is a lot easier, and proper locking is already > there :) > > Jeff > > > - > To unsubscribe from this list: send the line "unsubscribe linux-ide" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > [-- Attachment #2: pdc2027x.diff --] [-- Type: application/octet-stream, Size: 25770 bytes --] diff -Nru libata-pdc-2.6-ori/drivers/scsi/Kconfig libata-pdc-2.6/drivers/scsi/Kconfig --- libata-pdc-2.6-ori/drivers/scsi/Kconfig 2004-10-18 17:25:52.000000000 +0800 +++ libata-pdc-2.6/drivers/scsi/Kconfig 2004-10-18 17:27:36.759587840 +0800 @@ -441,6 +441,14 @@ If unsure, say N. +config SCSI_PATA_PDC2027X + tristate "Promise PATA 2027x support" + depends on SCSI_SATA && PCI + help + This option enables support for Promise PATA pdc20268 to pdc20277 host adapters. + + If unsure, say N. + config SCSI_SATA_PROMISE tristate "Promise SATA TX2/TX4 support" depends on SCSI_SATA && PCI diff -Nru libata-pdc-2.6-ori/drivers/scsi/Makefile libata-pdc-2.6/drivers/scsi/Makefile --- libata-pdc-2.6-ori/drivers/scsi/Makefile 2004-10-18 17:25:52.000000000 +0800 +++ libata-pdc-2.6/drivers/scsi/Makefile 2004-10-18 17:27:36.796582216 +0800 @@ -124,6 +124,7 @@ obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o +obj-$(CONFIG_SCSI_PATA_PDC2027X)+= libata.o pata_pdc2027x.o obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o diff -Nru libata-pdc-2.6-ori/drivers/scsi/pata_pdc2027x.c libata-pdc-2.6/drivers/scsi/pata_pdc2027x.c --- libata-pdc-2.6-ori/drivers/scsi/pata_pdc2027x.c 1970-01-01 08:00:00.000000000 +0800 +++ libata-pdc-2.6/drivers/scsi/pata_pdc2027x.c 2004-10-18 17:27:37.993400272 +0800 @@ -0,0 +1,758 @@ +/* + * Promise PATA TX2/TX4/TX2000/133 IDE driver for pdc20268 to pdc20277. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Ported to libata by: + * Albert Lee <albertcc@tw.ibm.com> IBM Corporation + * + * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> + * Portions Copyright (C) 1999 Promise Technology, Inc. + * + * Author: Frank Tiernan (frankt@promise.com) + * Released under terms of General Public License + * + * + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/blkdev.h> +#include <linux/delay.h> +#include "scsi.h" +#include <scsi/scsi_host.h> +#include <linux/libata.h> +#include <asm/io.h> + +#define DRV_NAME "pata_pdc2027x" +#define DRV_VERSION "0.52" +#undef PDC_DEBUG +#undef PDC_20276_QUIRK +#undef PDC_20270_QUIRK + +#ifdef PDC_DEBUG +#define PDPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args) +#else +#define PDPRINTK(fmt, args...) +#endif + +enum { + PDC_UDMA_100 = 0, + PDC_UDMA_133 = 1, + + PDC_100_MHZ = 100000000, + PDC_133_MHZ = 133333333, +}; + +static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +static void pdc2027x_remove_one(struct pci_dev *pdev); +static void pdc2027x_phy_reset(struct ata_port *ap); +static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev); +static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev); + +/* + * ATA Timing Tables based on 133MHz controller clock. + * These tables are only used when the controller is in 133MHz clock. + * If the controller is in 100MHz clock, the ASIC hardware will + * set the timing registers automatically when "set feature" command + * issued to the device. However, if the controller clock is 133MHz, + * the following tables must be used. + */ +static struct pdc2027x_pio_timing { + u8 value0, value1, value2; +} pdc2027x_pio_timing_tbl [] = { + { 0xfb, 0x2b, 0xac }, /* PIO mode 0 */ + { 0x46, 0x29, 0xa4 }, /* PIO mode 1 */ + { 0x23, 0x26, 0x64 }, /* PIO mode 2 */ + { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ + { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ +}; + +static struct pdc2027x_mdma_timing { + u8 value0, value1; +} pdc2027x_mdma_timing_tbl [] = { + { 0xdf, 0x5f }, /* MDMA mode 0 */ + { 0x6b, 0x27 }, /* MDMA mode 1 */ + { 0x69, 0x25 }, /* MDMA mode 2 */ +}; + +static struct pdc2027x_udma_timing { + u8 value0, value1, value2; +} pdc2027x_udma_timing_tbl [] = { + { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ + { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ + { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ + { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ + { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ + { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ + { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ +}; + +static struct pci_device_id pdc2027x_pci_tbl[] = { +#ifdef ATA_ENABLE_PATA + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_100 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_100 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, +#endif + { } /* terminate list */ +}; + +static struct pci_driver pdc2027x_pci_driver = { + .name = DRV_NAME, + .id_table = pdc2027x_pci_tbl, + .probe = pdc2027x_init_one, + .remove = __devexit_p(pdc2027x_remove_one), +}; + +static Scsi_Host_Template pdc2027x_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations pdc2027x_pata_ops = { + .port_disable = ata_port_disable, + .set_piomode = pdc2027x_set_piomode, + .set_dmamode = pdc2027x_set_dmamode, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .phy_reset = pdc2027x_phy_reset, + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static struct ata_port_info pdc2027x_port_info[] = { + /* PDC_UDMA_100 */ + { + .sht = &pdc2027x_sht, + .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_SRST, + .pio_mask = 0x03, /* pio3-4 */ + .mwdma_mask = 0x06, /* mwdma1-2 */ + .udma_mask = ATA_UDMA5, + .port_ops = &pdc2027x_pata_ops, + }, + /* PDC_UDMA_133 */ + { + .sht = &pdc2027x_sht, + .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_SRST, + .pio_mask = 0x03, /* pio3-4 */ + .mwdma_mask = 0x06, /* mwdma1-2 */ + .udma_mask = ATA_UDMA6, + .port_ops = &pdc2027x_pata_ops, + }, +}; + +MODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Albert Lee"); +MODULE_DESCRIPTION("libata driver module for Promise PDC20268 to PDC20277"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, pdc2027x_pci_tbl); + +/** + * pdc_get_indexed_reg - Set pdc202xx extended register + * @ap: Port to which the extended register is set + * @index: index of the extended register + */ +static u8 pdc_get_indexed_reg(struct ata_port *ap, u8 index) +{ + u8 tmp8; + + outb(index, ap->ioaddr.bmdma_addr + 1); + tmp8 = inb(ap->ioaddr.bmdma_addr + 3); + + PDPRINTK("Get index reg%X[%X] \n", index, tmp8); + return tmp8; +} +/** + * pdc_set_indexed_reg - Read pdc202xx extended register + * @ap: Port to which the extended register is read + * @index: index of the extended register + */ +static void pdc_set_indexed_reg(struct ata_port *ap, u8 index, u8 value) +{ + outb(index, ap->ioaddr.bmdma_addr + 1); + outb(value, ap->ioaddr.bmdma_addr + 3); + PDPRINTK("Set index reg%X[%X] \n", index, value); +} +/** + * pdc2027x_pata_cbl_detect - Probe host controller cable detect info + * @ap: Port for which cable detect info is desired + * + * Read 80c cable indicator from Promise extended register. + * This register is latched when the system is reset. + * + * LOCKING: + * None (inherited from caller). + */ +static void pdc2027x_cbl_detect(struct ata_port *ap) +{ + u8 cbl40c; + + /* check cable detect results */ + cbl40c = pdc_get_indexed_reg(ap, 0x0b) & 0x04; + + if (cbl40c) + goto cbl40; + + PDPRINTK("No cable or 80-conductor cable on port %d\n", ap->port_no); + + ap->cbl = ATA_CBL_PATA80; + return; + +cbl40: + printk(KERN_INFO DRV_NAME ": 40-conductor cable detected on port %d\n", ap->port_no); + ap->cbl = ATA_CBL_PATA40; + ap->udma_mask &= ATA_UDMA_MASK_40C; +} +/** + * pdc2027x_port_enabled - Check extended register at 0x04 to see whether the port is enabled. + * @ap: Port to check + */ +static inline int pdc2027x_port_enabled(struct ata_port *ap) +{ + return pdc_get_indexed_reg(ap, 0x04) & 0x02; +} +/** + * pdc2027x_phy_reset - Probe specified port on PATA host controller + * @ap: Port to probe + * + * Probe PATA phy. + * + * LOCKING: + * None (inherited from caller). + */ +static void pdc2027x_phy_reset(struct ata_port *ap) +{ + /* Check whether port enabled */ + if (!pdc2027x_port_enabled(ap)) { + ata_port_disable(ap); + printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + return; + } + + pdc2027x_cbl_detect(ap); + ata_port_probe(ap); + ata_bus_reset(ap); +} +/** + * pdc2027x_set_piomode - Initialize host controller PATA PIO timings + * @ap: Port to configure + * @adev: um + * @pio: PIO mode, 0 - 4 + * + * Set PIO mode for device. + * + * LOCKING: + * None (inherited from caller). + */ +static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ + unsigned int pio = adev->pio_mode - XFER_PIO_0; + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; + u8 adj = (drive_dn%2) ? 0x08 : 0x00; + u8 tmp8; + + + PDPRINTK("adev->pio_mode[%X]\n", adev->pio_mode); + + /* Sanity check */ + if(pio > 4) { + printk(KERN_ERR DRV_NAME ": Unknown pio mode [%d] ignored\n", pio); + return; + + } + + /* Set the PIO timing registers using value table for 133MHz */ + PDPRINTK("Set pio regs... \n"); + + pdc_set_indexed_reg(ap, 0x0c + adj, pdc2027x_pio_timing_tbl[pio].value0); + pdc_set_indexed_reg(ap, 0x0d + adj, pdc2027x_pio_timing_tbl[pio].value1); + pdc_set_indexed_reg(ap, 0x13 + adj, pdc2027x_pio_timing_tbl[pio].value2); + + PDPRINTK("Set pio regs done\n"); + + /* + * Check whether the device supports turning off IORDY. + * For PIO3 and above, the device must support IORDY and set bit 10 + */ + if (adev->id[49] & 0x400) { + /* IORDY_EN & PREFETCH_EN */ + /* Turn on Prefetch */ + tmp8 = pdc_get_indexed_reg(ap, 0x13 + adj); + pdc_set_indexed_reg(ap, 0x13 + adj, tmp8 | 0x03); + + PDPRINTK("Turn on prefetch\n"); + } + + printk(KERN_INFO DRV_NAME ": Set to pio mode[%u] \n", pio); +} +/** + * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings + * @ap: Port to configure + * @adev: um + * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6 + * + * Set UDMA mode for device. + * + * LOCKING: + * None (inherited from caller). + */ +static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev) +{ + unsigned int dma_mode = adev->dma_mode; + unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno; + u8 adj = (drive_dn%2) ? 0x08 : 0x00; + u8 tmp8; + + if((dma_mode >= XFER_UDMA_0) && + (dma_mode <= XFER_UDMA_6)) { + /* Set the UDMA timing registers with value table for 133MHz */ + unsigned int udma_mode = dma_mode & 0x07; + + if (dma_mode == XFER_UDMA_2) { + /* + * Turn off tHOLD. + * If tHOLD is '1', the hardware will add half clock for data hold time. + * This code segment seems to be no effect. tHOLD will be overwritten below. + */ + tmp8 = pdc_get_indexed_reg(ap, 0x10 + adj); + pdc_set_indexed_reg(ap, 0x10 + adj, tmp8 & 0x7f); + } + + PDPRINTK("Set udma regs... \n"); + pdc_set_indexed_reg(ap, 0x10 + adj, pdc2027x_udma_timing_tbl[udma_mode].value0); + pdc_set_indexed_reg(ap, 0x11 + adj, pdc2027x_udma_timing_tbl[udma_mode].value1); + pdc_set_indexed_reg(ap, 0x12 + adj, pdc2027x_udma_timing_tbl[udma_mode].value2); + PDPRINTK("Set udma regs done\n"); + + printk(KERN_INFO DRV_NAME ": Set to udma mode[%u] \n", udma_mode); + + } else if((dma_mode >= XFER_MW_DMA_0) && + (dma_mode <= XFER_MW_DMA_2)) { + /* Set the MDMA timing registers with value table for 133MHz */ + unsigned int mdma_mode = dma_mode & 0x07; + + PDPRINTK("Set mdma regs... \n"); + pdc_set_indexed_reg(ap, 0x0e + adj, pdc2027x_mdma_timing_tbl[mdma_mode].value0); + pdc_set_indexed_reg(ap, 0x0f + adj, pdc2027x_mdma_timing_tbl[mdma_mode].value1); + PDPRINTK("Set mdma regs done\n"); + + printk(KERN_INFO DRV_NAME ": Set to mdma mode[%u] \n", mdma_mode); + } else { + printk(KERN_ERR DRV_NAME ": Unknown dma mode [%u] ignored\n", dma_mode); + } +} +/** + * adjust_pll - Adjust the PLL input clock in Hz. + * + * @pdc_controller: controller specific information + * @probe_ent: For the port address + * @pll_clock: The input of PLL in HZ + */ +static void pdc_adjust_pll(struct ata_probe_ent *probe_ent, long pll_clock, unsigned int board_idx) +{ + + u8 pll_ctl0, pll_ctl1; + long pll_clock_khz = pll_clock / 1000; + long pout_required = board_idx? PDC_133_MHZ:PDC_100_MHZ; + long ratio = pout_required / pll_clock_khz; + int F, R; + + + /* Sanity check */ + if (unlikely(pll_clock_khz < 5000L || pll_clock_khz > 70000L)) { + printk(KERN_ERR DRV_NAME ": Invalid PLL input clock %ldkHz, give up!\n", pll_clock_khz); + return; + } + +#ifdef PDC_DEBUG + PDPRINTK("pout_required is %ld\n", pout_required); + + /* Show the current clock value of PLL control register + * (maybe already configured by the firmware) + */ + outb(0x02, probe_ent->port[1].bmdma_addr + 0x01); + pll_ctl0 = inb(probe_ent->port[1].bmdma_addr + 0x03); + outb(0x03, probe_ent->port[1].bmdma_addr + 0x01); + pll_ctl1 = inb(probe_ent->port[1].bmdma_addr + 0x03); + + PDPRINTK("pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1); +#endif + + /* + * Calculate the ratio of F, R and OD + * POUT = (F + 2) / (( R + 2) * NO) + */ + if (ratio < 8600L) { // 8.6x + /* Using NO = 0x01, R = 0x0D */ + R = 0x0d; + } else if (ratio < 12900L) { // 12.9x + /* Using NO = 0x01, R = 0x08 */ + R = 0x08; + } else if (ratio < 16100L) { // 16.1x + /* Using NO = 0x01, R = 0x06 */ + R = 0x06; + } else if (ratio < 64000L) { // 64x + R = 0x00; + } else { + /* Invalid ratio */ + printk(KERN_ERR DRV_NAME ": Invalid ratio %ld, give up!\n", ratio); + return; + } + + F = (ratio * (R+2)) / 1000 - 2; + + if (unlikely(F < 0 || F > 127)) { + /* Invalid F */ + printk(KERN_ERR DRV_NAME ": F[%d] invalid!\n", F); + return; + } + + PDPRINTK("F[%d] R[%d] ratio*1000[%ld]\n", F, R, ratio); + + pll_ctl0 = (u8) F; + pll_ctl1 = (u8) R; + + PDPRINTK("Writing pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1); + + outb(0x02, probe_ent->port[1].bmdma_addr + 0x01); + outb(pll_ctl0, probe_ent->port[1].bmdma_addr + 0x03); + outb(0x03, probe_ent->port[1].bmdma_addr + 0x01); + outb(pll_ctl1, probe_ent->port[1].bmdma_addr + 0x03); + + /* Wait the PLL circuit to be stable */ + mdelay(30); + +#ifdef PDC_DEBUG + /* + * Show the current clock value of PLL control register + * (maybe configured by the firmware) + */ + outb(0x02, probe_ent->port[1].bmdma_addr + 0x01); + pll_ctl0 = inb(probe_ent->port[1].bmdma_addr + 0x03); + outb(0x03, probe_ent->port[1].bmdma_addr + 0x01); + pll_ctl1 = inb(probe_ent->port[1].bmdma_addr + 0x03); + + PDPRINTK("pll_ctl[%X][%X]\n", pll_ctl0, pll_ctl1); +#endif + + return; +} +/** + * detect_pll_input_clock - Detect the PLL input clock in Hz. + * @probe_ent: for the port address + * Ex. 16949000 on 33MHz PCI bus for pdc20275. + * Half of the PCI clock. + */ +static long pdc_detect_pll_input_clock(struct ata_probe_ent *probe_ent) +{ + u8 scr1; + unsigned long ctr0; + unsigned long ctr1; + unsigned long ctr2 = 0; + unsigned long ctr3 = 0; + + unsigned long start_count, end_count; + long pll_clock; + + /* Read current counter value */ + outb(0x20, probe_ent->port[0].bmdma_addr + 0x01); + ctr0 = inb(probe_ent->port[0].bmdma_addr + 0x03); + outb(0x21, probe_ent->port[0].bmdma_addr + 0x01); + ctr1 = inb(probe_ent->port[0].bmdma_addr + 0x03); + + outb(0x20, probe_ent->port[1].bmdma_addr + 0x01); + ctr2 = inb(probe_ent->port[1].bmdma_addr + 0x03); + outb(0x21, probe_ent->port[1].bmdma_addr + 0x01); + ctr3 = inb(probe_ent->port[1].bmdma_addr + 0x03); + + start_count = (ctr3 << 23 ) | (ctr2 << 15) | (ctr1 << 8) | ctr0; + + PDPRINTK("ctr0[%lX] ctr1[%lX] ctr2 [%lX] ctr3 [%lX]\n", ctr0, ctr1, ctr2, ctr3); + + /* Start the test mode */ + outb(0x01, probe_ent->port[0].bmdma_addr + 0x01); + scr1 = inb(probe_ent->port[0].bmdma_addr + 0x03); + PDPRINTK("scr1[%X]\n", scr1); + outb(scr1 | 0x40, probe_ent->port[0].bmdma_addr + 0x03); + + /* Let the counter run for 1000 us. */ + udelay(1000); + + /* Read the counter values again */ + outb(0x20, probe_ent->port[0].bmdma_addr + 0x01); + ctr0 = inb(probe_ent->port[0].bmdma_addr + 0x03); + outb(0x21, probe_ent->port[0].bmdma_addr + 0x01); + ctr1 = inb(probe_ent->port[0].bmdma_addr + 0x03); + + outb(0x20, probe_ent->port[1].bmdma_addr + 0x01); + ctr2 = inb(probe_ent->port[1].bmdma_addr + 0x03); + outb(0x21, probe_ent->port[1].bmdma_addr + 0x01); + ctr3 = inb(probe_ent->port[1].bmdma_addr + 0x03); + + end_count = (ctr3 << 23 ) | (ctr2 << 15) | (ctr1 << 8) | ctr0; + + PDPRINTK("ctr0[%lX] ctr1[%lX] ctr2 [%lX] ctr3 [%lX]\n", ctr0, ctr1, ctr2, ctr3); + + /* Stop the test mode */ + outb(0x01, probe_ent->port[0].bmdma_addr + 0x01); + scr1 = inb(probe_ent->port[0].bmdma_addr + 0x03); + PDPRINTK("scr1[%X]\n", scr1); + outb(scr1 & 0xBF, probe_ent->port[0].bmdma_addr + 0x03); + + /* calculate the input clock in Hz */ + pll_clock = (long) ((start_count - end_count) * 1000); + + PDPRINTK("start[%lu] end[%lu] \n", start_count, end_count); + PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock); + + return pll_clock; +} +/** + * pdc_hardware_init - Initialize the hardware. + * @pdev: instance of pci_dev found + * @pdc_controller: controller specific information + * @pe: for the port address + */ +static int pdc_hardware_init(struct pci_dev *pdev, struct ata_probe_ent *pe, unsigned int board_idx) +{ + long pll_clock; + + /* Enable the ROM */ + /* + if (pdev->resource[PCI_ROM_RESOURCE].start) { + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, + pdev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + printk(KERN_INFO DRV_NAME ": ROM enabled at 0x%08lx\n", + pdev->resource[PCI_ROM_RESOURCE].start); + } + */ + + /* + * Detect PLL input clock rate. + * On some system, where PCI bus is running at non-standard clock rate. + * Ex. 25MHz or 40MHz, we have to adjust the cycle_time. + * The pdc20275 controller employs PLL circuit to help correct timing registers setting. + */ + pll_clock = pdc_detect_pll_input_clock(pe); + + if(pll_clock < 0) /* counter overflow? Try again. */ + pll_clock = pdc_detect_pll_input_clock(pe); + + printk(KERN_INFO DRV_NAME ": PLL input clock %ld kHz\n", pll_clock/1000); + + /* Adjust PLL control register */ + pdc_adjust_pll(pe, pll_clock, board_idx); + + return 0; +} +/** + * pdc2027x_init_one - PCI probe function + * Called when an instance of PCI adapter is inserted. + * This function checks whether the hardware is supported, + * initialize hardware and register an instance of ata_host_set to + * libata by providing struct ata_probe_ent and ata_device_add(). + * (implements struct pci_driver.probe() ) + * + * @pdev: instance of pci_dev found + * @ent: matching entry in the id_tbl[] + */ +static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + unsigned int board_idx = (unsigned int) ent->driver_data; + + struct ata_probe_ent *probe_ent = NULL; + int rc; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + +#ifdef PDC_20276_QUIRK + /* + * Skip Promise PDC20276 attached to I2O RAID controller + */ + if ((pdev->device == PCI_DEVICE_ID_PROMISE_20276) && + (pdev->bus->self) && + (pdev->bus->self->vendor == PCI_VENDOR_ID_INTEL) && + ((pdev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) || + (pdev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM))) { + printk(KERN_INFO DRV_NAME ": Skipping Promise PDC20276 " + "attached to I2O RAID controller.\n"); + return -ENODEV; + } +#endif + +#ifdef PDC_20270_QUIRK + /* + * Special IRQ handling for Promise PDC20270 attached to the + * DEC DC21150 PCI south bridge. (DC21150 PCI bridge can be found + * on Compaq ProLiant 800 and ProLiant 1600 servers.) + * FIXME: Not tested yet on libata. + */ + if ((pdev->device == PCI_DEVICE_ID_PROMISE_20270) && + (pdev->bus->self) && + (pdev->bus->self->vendor == PCI_VENDOR_ID_DEC) && + (pdev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { + struct pci_dev *findev = NULL; + + if (PCI_SLOT(pdev->devfn) & 2) { + /* This pdc20270 is in PCI slot with bit 1 set. + * Find the other pdc20270 in PCI slot with bit 1 cleared. + * If found, override my IRQ setting to irq of that device. + */ + //d->extra = 0; // No extra DMA address on pdc20270 + + while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { + if ((findev->vendor == pdev->vendor) && + (findev->device == pdev->device) && + (!(PCI_SLOT(findev->devfn) & 2))) { + + if (pdev->irq != findev->irq) { + // Override the IRQ setting + pdev->irq = findev->irq; + break; + } + } + } + } + + } +#endif + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + /* Prepare the probe entry */ + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) { + rc = -ENOMEM; + goto err_out_regions; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->pdev = pdev; + INIT_LIST_HEAD(&probe_ent->node); + + probe_ent->sht = pdc2027x_port_info[board_idx].sht; + probe_ent->host_flags = pdc2027x_port_info[board_idx].host_flags; + probe_ent->pio_mask = pdc2027x_port_info[board_idx].pio_mask; + probe_ent->udma_mask = pdc2027x_port_info[board_idx].udma_mask; + probe_ent->port_ops = pdc2027x_port_info[board_idx].port_ops; + + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + + probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); + ata_std_ports(&probe_ent->port[0]); + probe_ent->port[0].altstatus_addr = + probe_ent->port[0].ctl_addr = + pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; + probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); + + probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); + ata_std_ports(&probe_ent->port[1]); + probe_ent->port[1].altstatus_addr = + probe_ent->port[1].ctl_addr = + pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; + probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; + + probe_ent->n_ports = 2; + + pci_set_master(pdev); + //pci_enable_intx(pdev); + + /* initialize adapter */ + if(pdc_hardware_init(pdev, probe_ent, board_idx) != 0) + goto err_out_free_ent; + + ata_device_add(probe_ent); + kfree(probe_ent); + + return 0; + +err_out_free_ent: + kfree(probe_ent); +err_out_regions: + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} +/** + * pdc2027x_remove_one - Called to remove a single instance of the + * adapter. + * + * @dev: The PCI device to remove. + * FIXME: module load/unload not working yet + */ +static void __devexit pdc2027x_remove_one(struct pci_dev *pdev) +{ + ata_pci_remove_one(pdev); +} +/** + * pdc2027x_init - Called after this module is loaded into the kernel. + */ +static int __init pdc2027x_init(void) +{ + return pci_module_init(&pdc2027x_pci_driver); +} +/** + * pdc2027x_exit - Called before this module unloaded from the kernel + */ +static void __exit pdc2027x_exit(void) +{ + pci_unregister_driver(&pdc2027x_pci_driver); +} + +module_init(pdc2027x_init); +module_exit(pdc2027x_exit); ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-18 10:30 ` Albert Lee @ 2004-10-18 17:00 ` Jeff Garzik 2004-10-18 17:26 ` Jeff Garzik 2004-10-21 8:36 ` Albert Lee 0 siblings, 2 replies; 11+ messages in thread From: Jeff Garzik @ 2004-10-18 17:00 UTC (permalink / raw) To: Albert Lee; +Cc: Bartlomiej Zolnierkiewicz, IDE Linux I'm applying to libata-dev, but won't push this upstream for a while. My comments: 1) why is ROM enabled? Normally you don't want to do this. + /* Enable the ROM */ + /* + if (pdev->resource[PCI_ROM_RESOURCE].start) { + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, + pdev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS _ENABLE); 2) why does this quirk exist? if pata_pdc2027x (libata) will work with this hardware, then remove this code (and quirk) completely. It is up to the user to choose the correct driver, if multiple drivers will function properly on the hardware. +#ifdef PDC_20276_QUIRK + /* + * Skip Promise PDC20276 attached to I2O RAID controller + */ + if ((pdev->device == PCI_DEVICE_ID_PROMISE_20276) && + (pdev->bus->self) && + (pdev->bus->self->vendor == PCI_VENDOR_ID_INTEL) && + ((pdev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) || + (pdev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM))) { + printk(KERN_INFO DRV_NAME ": Skipping Promise PDC20276 " + "attached to I2O RAID controller.\n"); + return -ENODEV; + } +#endif 3) the quirk PDC_20270_QUIRK needs work to conform to current PCI API standards. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-18 17:00 ` Jeff Garzik @ 2004-10-18 17:26 ` Jeff Garzik 2004-10-21 8:36 ` Albert Lee 1 sibling, 0 replies; 11+ messages in thread From: Jeff Garzik @ 2004-10-18 17:26 UTC (permalink / raw) To: Albert Lee; +Cc: Bartlomiej Zolnierkiewicz, IDE Linux Oh and BTW, you forgot your signed-off-by line: http://linux.yyz.us/patch-format.html ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-18 17:00 ` Jeff Garzik 2004-10-18 17:26 ` Jeff Garzik @ 2004-10-21 8:36 ` Albert Lee 2004-10-21 23:10 ` Jeff Garzik 1 sibling, 1 reply; 11+ messages in thread From: Albert Lee @ 2004-10-21 8:36 UTC (permalink / raw) To: Jeff Garzik; +Cc: Bartlomiej Zolnierkiewicz, IDE Linux Hi, Jeff: Please see my reply below. I'll resend the patch according to your review/comments later. Thanks for your patience for newbie like me. :-) Thanks, Albert ----- Original Message ----- From: "Jeff Garzik" <jgarzik@pobox.com> To: "Albert Lee" <albertcc@tw.ibm.com> Cc: "Bartlomiej Zolnierkiewicz" <bzolnier@gmail.com>; "IDE Linux" <linux-ide@vger.kernel.org> Sent: Tuesday, October 19, 2004 1:00 AM Subject: Re: [PATCH/RFC] Port of pdc202xx_new driver to libata > I'm applying to libata-dev, but won't push this upstream for a while. > > My comments: > > 1) why is ROM enabled? Normally you don't want to do this. > > + /* Enable the ROM */ > + /* > + if (pdev->resource[PCI_ROM_RESOURCE].start) { > + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, > + pdev->resource[PCI_ROM_RESOURCE].start | > PCI_ROM_ADDRESS > _ENABLE); > Ported from the original driver blindly. I'll remove this stuff. > > > 2) why does this quirk exist? if pata_pdc2027x (libata) will work with > this hardware, then remove this code (and quirk) completely. It is up > to the user to choose the correct driver, if multiple drivers will > function properly on the hardware. > > +#ifdef PDC_20276_QUIRK > + /* > + * Skip Promise PDC20276 attached to I2O RAID controller > + */ > + if ((pdev->device == PCI_DEVICE_ID_PROMISE_20276) && > + (pdev->bus->self) && > + (pdev->bus->self->vendor == PCI_VENDOR_ID_INTEL) && > + ((pdev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) || > + (pdev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM))) { > + printk(KERN_INFO DRV_NAME ": Skipping Promise PDC20276 " > + "attached to I2O RAID controller.\n"); > + return -ENODEV; > + } > +#endif > Ported from the original driver blindly, too. :-( I don't know why the original driver doesn't support it. I'll remove it, too. > > > 3) the quirk PDC_20270_QUIRK needs work to conform to current PCI API > standards. > > Could this also be removed? This is also ported blindly from the original driver. :-( It seems to be a bug of DEC21150 PCI south bridge chip, but there is no detail about the actual problem. (I've searched the archive, but no clue found.) > > - > To unsubscribe from this list: send the line "unsubscribe linux-ide" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-21 8:36 ` Albert Lee @ 2004-10-21 23:10 ` Jeff Garzik 2004-10-22 2:32 ` Albert Lee 0 siblings, 1 reply; 11+ messages in thread From: Jeff Garzik @ 2004-10-21 23:10 UTC (permalink / raw) To: Albert Lee; +Cc: Bartlomiej Zolnierkiewicz, IDE Linux Albert Lee wrote: > Hi, Jeff: > > Please see my reply below. > I'll resend the patch according to your review/comments later. > Thanks for your patience for newbie like me. :-) Note that I applied your patch... so please just send a follow-up patch, diff'd against the latest libata-dev patch/BK. http://marc.theaimsgroup.com/?t=109782787200002&r=1&w=2&n=4 Jeff ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-21 23:10 ` Jeff Garzik @ 2004-10-22 2:32 ` Albert Lee 2004-10-27 14:46 ` Jeff Garzik 0 siblings, 1 reply; 11+ messages in thread From: Albert Lee @ 2004-10-22 2:32 UTC (permalink / raw) To: Jeff Garzik; +Cc: IDE Linux [-- Attachment #1: Type: text/plain, Size: 1008 bytes --] Jeff: Attached please find the patch, thanks. Albert Signed-off-by: Albert Lee<albertcc@tw.ibm.com> ----- Original Message ----- From: "Jeff Garzik" <jgarzik@pobox.com> To: "Albert Lee" <albertcc@tw.ibm.com> Cc: "Bartlomiej Zolnierkiewicz" <bzolnier@gmail.com>; "IDE Linux" <linux-ide@vger.kernel.org> Sent: Friday, October 22, 2004 7:10 AM Subject: Re: [PATCH/RFC] Port of pdc202xx_new driver to libata > Albert Lee wrote: > > Hi, Jeff: > > > > Please see my reply below. > > I'll resend the patch according to your review/comments later. > > Thanks for your patience for newbie like me. :-) > > Note that I applied your patch... so please just send a follow-up patch, > diff'd against the latest libata-dev patch/BK. > > http://marc.theaimsgroup.com/?t=109782787200002&r=1&w=2&n=4 > > Jeff > > > - > To unsubscribe from this list: send the line "unsubscribe linux-ide" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > [-- Attachment #2: pdc2027x-2.diff --] [-- Type: application/octet-stream, Size: 3453 bytes --] diff -Nru libata-pdc2-2.6/drivers/scsi/pata_pdc2027x.c libata-pdc2-2.6-mod/drivers/scsi/pata_pdc2027x.c --- libata-pdc2-2.6/drivers/scsi/pata_pdc2027x.c 2004-10-21 17:17:40.000000000 +0800 +++ libata-pdc2-2.6-mod/drivers/scsi/pata_pdc2027x.c 2004-10-21 17:28:06.990919600 +0800 @@ -29,10 +29,8 @@ #include <asm/io.h> #define DRV_NAME "pata_pdc2027x" -#define DRV_VERSION "0.52" +#define DRV_VERSION "0.53" #undef PDC_DEBUG -#undef PDC_20276_QUIRK -#undef PDC_20270_QUIRK #ifdef PDC_DEBUG #define PDPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args) @@ -59,7 +57,7 @@ * These tables are only used when the controller is in 133MHz clock. * If the controller is in 100MHz clock, the ASIC hardware will * set the timing registers automatically when "set feature" command - * issued to the device. However, if the controller clock is 133MHz, + * is issued to the device. However, if the controller clock is 133MHz, * the following tables must be used. */ static struct pdc2027x_pio_timing { @@ -554,16 +552,6 @@ { long pll_clock; - /* Enable the ROM */ - /* - if (pdev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(pdev, PCI_ROM_ADDRESS, - pdev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk(KERN_INFO DRV_NAME ": ROM enabled at 0x%08lx\n", - pdev->resource[PCI_ROM_RESOURCE].start); - } - */ - /* * Detect PLL input clock rate. * On some system, where PCI bus is running at non-standard clock rate. @@ -604,58 +592,6 @@ if (!printed_version++) printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); -#ifdef PDC_20276_QUIRK - /* - * Skip Promise PDC20276 attached to I2O RAID controller - */ - if ((pdev->device == PCI_DEVICE_ID_PROMISE_20276) && - (pdev->bus->self) && - (pdev->bus->self->vendor == PCI_VENDOR_ID_INTEL) && - ((pdev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) || - (pdev->bus->self->device == PCI_DEVICE_ID_INTEL_I960RM))) { - printk(KERN_INFO DRV_NAME ": Skipping Promise PDC20276 " - "attached to I2O RAID controller.\n"); - return -ENODEV; - } -#endif - -#ifdef PDC_20270_QUIRK - /* - * Special IRQ handling for Promise PDC20270 attached to the - * DEC DC21150 PCI south bridge. (DC21150 PCI bridge can be found - * on Compaq ProLiant 800 and ProLiant 1600 servers.) - * FIXME: Not tested yet on libata. - */ - if ((pdev->device == PCI_DEVICE_ID_PROMISE_20270) && - (pdev->bus->self) && - (pdev->bus->self->vendor == PCI_VENDOR_ID_DEC) && - (pdev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { - struct pci_dev *findev = NULL; - - if (PCI_SLOT(pdev->devfn) & 2) { - /* This pdc20270 is in PCI slot with bit 1 set. - * Find the other pdc20270 in PCI slot with bit 1 cleared. - * If found, override my IRQ setting to irq of that device. - */ - //d->extra = 0; // No extra DMA address on pdc20270 - - while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { - if ((findev->vendor == pdev->vendor) && - (findev->device == pdev->device) && - (!(PCI_SLOT(findev->devfn) & 2))) { - - if (pdev->irq != findev->irq) { - // Override the IRQ setting - pdev->irq = findev->irq; - break; - } - } - } - } - - } -#endif - rc = pci_enable_device(pdev); if (rc) return rc; ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH/RFC] Port of pdc202xx_new driver to libata 2004-10-22 2:32 ` Albert Lee @ 2004-10-27 14:46 ` Jeff Garzik 0 siblings, 0 replies; 11+ messages in thread From: Jeff Garzik @ 2004-10-27 14:46 UTC (permalink / raw) To: Albert Lee; +Cc: IDE Linux Albert Lee wrote: > Jeff: > > Attached please find the patch, thanks. > > Albert > > Signed-off-by: Albert Lee<albertcc@tw.ibm.com> Patch applied. But next line, please include a description of the patch in your email body, and subject line. See rules #1 and #2 at http://linux.yyz.us/patch-format.html Thanks, Jeff ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2004-10-27 14:47 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-10-13 10:06 [PATCH/RFC] Port of pdc202xx_new driver to libata Albert Lee 2004-10-13 19:32 ` Bartlomiej Zolnierkiewicz 2004-10-13 19:58 ` Jeff Garzik 2004-10-13 20:16 ` Bartlomiej Zolnierkiewicz 2004-10-18 10:30 ` Albert Lee 2004-10-18 17:00 ` Jeff Garzik 2004-10-18 17:26 ` Jeff Garzik 2004-10-21 8:36 ` Albert Lee 2004-10-21 23:10 ` Jeff Garzik 2004-10-22 2:32 ` Albert Lee 2004-10-27 14:46 ` Jeff Garzik
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).