Hi ! I am new on the list. I try to get ep93xx pata driver from Alessandro Zummo running on 2.6.20-rc1. The driver supports for now no DMA but i think PIO or MMIO, what is the difference? You see I am a newbe to ata ... sorry The problem is that ata_interrupt comes always and the system hangs: I have added some printks to ata_interrupt: ep93xx_pata_probe: : ioremap to 0xc685a000 pata_ep93xx pata_ep93xx: version 0.1 ata_device_add: ENTER ata_port_add: ENTER ata_port_start: prd alloc, virt ffc97000, dma 5d9a000 ata1: PATA max PIO4 cmd 0xC685A002 ctl 0xC685A019 bmdma 0x0 irq 40 ata_device_add: probe begin scsi0 : pata_ep93xx ata_device_add: ata1: bus probe begin ata_bus_reset: ENTER, host 1, port 0 ata_bus_softreset: ata1: bus reset via SRST ata_dev_classify: found ATA device by sig ata_bus_reset: EXIT ata1: ata_dev_select: ENTER, ata1: device 0, wait 1 ata1: ata_dev_select: ENTER, ata1: device 0, wait 1 ep93xx_exec_command: ata1: cmd 0xEC ATA INTERRUPT 1 ATA INTERRUPT 2 ** ap->flags 18 ATA INTERRUPT 3 if (qc) (qc->tf.flags & ATA_TFLAG_POLLING) qc->tf.flags 40 (qc->flags & ATA_QCFLAG_ACTIVE) --> It looks like that the ATA_TFLAG_POLLING is alsways set. So Interrupt alsways returns 0 because it is not handled. --> Does someone have any information about that for me what i can do or is there a problem in the driver ? Thanks a lot for help, happy x-mas, regards manfred attached is the driver: -- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/drivers/ata/pata_ep93xx.c 2006-12-20 16:51:02.192065229 +0100 @@ -0,0 +1,378 @@ +/* + * EP93XX PATA controller driver. + * Copyright (c) 2006 Tower Technologies + * Author: Alessandro Zummo <a.zummo@xxxxxxxxxxxx> + * + * An ATA driver to handle the embedded IDE controller + * of the Cirrus Logic EP93XX. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/libata.h> +#include <linux/irq.h> +#include <scsi/scsi_host.h> +#include <linux/platform_device.h> + +#define DRV_NAME "pata_ep93xx" +#define DRV_VERSION "0.1" + +struct ep93xx_pata_data { + void __iomem *mem; + int irq; +}; + +struct ata_host *ep93xx_host; + +static inline void ep93xx_toggle_wr(register u32 ctrl) +{ + ctrl &= ~(EP93XX_IDE_CTRL_DIOWn); + __raw_writel(ctrl, EP93XX_IDE_CTRL); + + ctrl |= EP93XX_IDE_CTRL_DIOWn; + __raw_writel(ctrl, EP93XX_IDE_CTRL); +} + +static inline void ep93xx_toggle_rd(register u32 ctrl) +{ + ctrl &= ~(EP93XX_IDE_CTRL_DIORn); + __raw_writel(ctrl, EP93XX_IDE_CTRL); + + ctrl |= EP93XX_IDE_CTRL_DIORn; + __raw_writel(ctrl, EP93XX_IDE_CTRL); +} + +#define ep93xx_write_addr(ctrl,addr) { \ + ctrl = (ctrl & ~(EP93XX_IDE_CTRL_DA_CS_MASK)) | EP93XX_IDE_CTRL_DA_CS(addr); \ + __raw_writel(ctrl, EP93XX_IDE_CTRL); } + +static inline void ep93xx_writew(register u16 value, volatile void __iomem *p) +{ + register u32 ctrl = __raw_readl(EP93XX_IDE_CTRL); + ep93xx_write_addr(ctrl, (unsigned long) p); + __raw_writel(value, EP93XX_IDE_DATAOUT); + ep93xx_toggle_wr(ctrl); +} + +#define ep93xx_writeb(value,addr) ep93xx_writew(value,addr) + +static inline unsigned short ep93xx_readw(volatile void __iomem *p) +{ + register u32 ctrl = __raw_readl(EP93XX_IDE_CTRL); + + ep93xx_write_addr(ctrl, (unsigned long) p); + ep93xx_toggle_rd(ctrl); + return __raw_readl(EP93XX_IDE_DATAIN); +} + +#define ep93xx_readb(addr) ep93xx_readw(addr) + +static unsigned long ep93xx_mode_filter(const struct ata_port *ap, + struct ata_device *adev, unsigned long mask) +{ + return mask; +} + +static void ep93xx_set_mode(struct ata_port *ap) +{ + int i; + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + if (ata_dev_enabled(dev)) { + dev->pio_mode = XFER_PIO_0; + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; + } + } +} + +static void ep93xx_phy_reset(struct ata_port *ap) +{ + ap->cbl = ATA_CBL_PATA40; + ata_port_probe(ap); + ata_bus_reset(ap); +} + +static void ep93xx_irq_clear(struct ata_port *ap) +{ +} + +static void ep93xx_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + + if (tf->ctl != ap->last_ctl) { + ep93xx_writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } + + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { + ep93xx_writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr); + ep93xx_writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr); + ep93xx_writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr); + ep93xx_writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr); + ep93xx_writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr); + VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", + tf->hob_feature, + tf->hob_nsect, + tf->hob_lbal, + tf->hob_lbam, + tf->hob_lbah); + } + + if (is_addr) { + ep93xx_writeb(tf->feature, (void __iomem *) ioaddr->feature_addr); + ep93xx_writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr); + ep93xx_writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr); + ep93xx_writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr); + ep93xx_writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr); + VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", + tf->feature, + tf->nsect, + tf->lbal, + tf->lbam, + tf->lbah); + } + + if (tf->flags & ATA_TFLAG_DEVICE) { + ep93xx_writeb(tf->device, (void __iomem *) ioaddr->device_addr); + VPRINTK("device 0x%X\n", tf->device); + } + + ata_wait_idle(ap); +} + +static void ep93xx_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + + tf->command = ap->ops->check_status(ap); + tf->feature = ep93xx_readb((void __iomem *)ioaddr->error_addr); + tf->nsect = ep93xx_readb((void __iomem *)ioaddr->nsect_addr); + tf->lbal = ep93xx_readb((void __iomem *)ioaddr->lbal_addr); + tf->lbam = ep93xx_readb((void __iomem *)ioaddr->lbam_addr); + tf->lbah = ep93xx_readb((void __iomem *)ioaddr->lbah_addr); + tf->device = ep93xx_readb((void __iomem *)ioaddr->device_addr); + + if (tf->flags & ATA_TFLAG_LBA48) { + ep93xx_writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr); + tf->hob_feature = ep93xx_readb((void __iomem *)ioaddr->error_addr); + tf->hob_nsect = ep93xx_readb((void __iomem *)ioaddr->nsect_addr); + tf->hob_lbal = ep93xx_readb((void __iomem *)ioaddr->lbal_addr); + tf->hob_lbam = ep93xx_readb((void __iomem *)ioaddr->lbam_addr); + tf->hob_lbah = ep93xx_readb((void __iomem *)ioaddr->lbah_addr); + } +} + +static u8 ep93xx_check_status(struct ata_port *ap) +{ + return ep93xx_readb((void __iomem *) ap->ioaddr.status_addr); +} + +static u8 ep93xx_check_altstatus(struct ata_port *ap) +{ + return ep93xx_readb((void __iomem *)ap->ioaddr.altstatus_addr); +} + +static void ep93xx_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) +{ + DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); + + ep93xx_writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr); + ata_pause(ap); +} + +static void ep93xx_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) +{ + unsigned int i; + unsigned int words = buflen >> 1; + u16 *buf16 = (u16 *) buf; + struct ata_port *ap = adev->ap; + void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; + + /* Transfer multiple of 2 bytes */ + if (write_data) { + for (i = 0; i < words; i++) + ep93xx_writew(le16_to_cpu(buf16[i]), mmio); + } else { + for (i = 0; i < words; i++) + buf16[i] = cpu_to_le16(ep93xx_readw(mmio)); + } + + /* Transfer trailing 1 byte, if any. */ + if (unlikely(buflen & 0x01)) { + u16 align_buf[1] = { 0 }; + unsigned char *trailing_buf = buf + buflen - 1; + + if (write_data) { + memcpy(align_buf, trailing_buf, 1); + ep93xx_writew(le16_to_cpu(align_buf[0]), mmio); + } else { + align_buf[0] = cpu_to_le16(ep93xx_readw(mmio)); + memcpy(trailing_buf, align_buf, 1); + } + } +} + +static struct scsi_host_template ep93xx_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .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 ep93xx_port_ops = { + .set_mode = ep93xx_set_mode, + .mode_filter = ep93xx_mode_filter, + + .port_disable = ata_port_disable, + .tf_load = ep93xx_tf_load, + .tf_read = ep93xx_tf_read, + .check_status = ep93xx_check_status, + .check_altstatus = ep93xx_check_altstatus, + .exec_command = ep93xx_exec_command, + .data_xfer = ep93xx_data_xfer, + + .dev_select = ata_std_dev_select, + + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + .irq_clear = ep93xx_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop, + + .phy_reset = ep93xx_phy_reset, +}; + +/* Setup the addresses and encode CSx within them */ +static void ep93xx_ports(struct ata_ioports *ioaddr,struct ep93xx_pata_data *data) +{ + ioaddr->cmd_addr = data->mem + 2; + ioaddr->altstatus_addr = data->mem + (0x06 << 2) + 1; + ioaddr->ctl_addr = data->mem + (0x06 << 2) + 1; + + ioaddr->data_addr = data->mem + (ATA_REG_DATA << 2) + 2; + ioaddr->error_addr = data->mem + (ATA_REG_ERR << 2) + 2; + ioaddr->feature_addr = data->mem + (ATA_REG_FEATURE << 2) + 2; + ioaddr->nsect_addr = data->mem + (ATA_REG_NSECT << 2) + 2; + ioaddr->lbal_addr = data->mem + (ATA_REG_LBAL << 2) + 2; + ioaddr->lbam_addr = data->mem + (ATA_REG_LBAM << 2) + 2; + ioaddr->lbah_addr = data->mem + (ATA_REG_LBAH << 2) + 2; + ioaddr->device_addr = data->mem + (ATA_REG_DEVICE << 2) + 2; + ioaddr->status_addr = data->mem + (ATA_REG_STATUS << 2) + 2; + ioaddr->command_addr = data->mem + (ATA_REG_CMD << 2) + 2; +} + +static __devinit int ep93xx_pata_probe(struct platform_device *pdev) +{ + int ret; + struct ata_probe_ent ae; + struct resource *res; + struct ep93xx_pata_data *data; + + memset(&ae, 0, sizeof(struct ata_probe_ent)); + INIT_LIST_HEAD(&ae.node); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + data->mem = ioremap(res->start,0x1000); + if (data->mem == NULL) { + dev_err(&pdev->dev, "Failed to ioremap pata registers\n"); + return -EIO; + } else { + DPRINTK(": ioremap to 0x%x \n",(unsigned int) data->mem); + } + + data->irq = platform_get_irq(pdev, 0); + if (data->irq) + set_irq_type(data->irq, IRQT_HIGH); + + ae.dev = &pdev->dev; + ae.port_ops = &ep93xx_port_ops; + ae.sht = &ep93xx_sht; + ae.n_ports = 1; + ae.pio_mask = 0x1f; /* PIO4 */ + ae.irq = data->irq; + ae.irq_flags = 0; + ae.port_flags = ATA_FLAG_MMIO | ATA_FLAG_SRST; + + ep93xx_ports(&ae.port[0], data); + + /* enable ide and set pio mode 4 */ + __raw_writel(EP93XX_IDE_CFG_IDEEN | EP93XX_IDE_CFG_PIO | + EP93XX_IDE_CFG_WST(0) | EP93XX_IDE_CFG_MODE(4), + EP93XX_IDE_CFG); + + /* run in polling mode if no irq has been assigned */ + if (!data->irq) + ae.port_flags |= ATA_FLAG_PIO_POLLING; + + dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); + + ret = ata_device_add(&ae); + if (ret == 0) + return -ENODEV; + + return 0; +} + +static __devexit int ep93xx_pata_remove(struct platform_device *dev) +{ + struct ata_host *host = platform_get_drvdata(dev); + + ata_host_remove(host); + platform_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver ep93xx_pata_platform_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ep93xx_pata_probe, + .remove = __devexit_p(ep93xx_pata_remove), +}; + + +static int __init ep93xx_pata_init(void) +{ + return platform_driver_register(&ep93xx_pata_platform_driver); +} + +static void __exit ep93xx_pata_exit(void) +{ + platform_driver_unregister(&ep93xx_pata_platform_driver); +} + +MODULE_AUTHOR("Alessandro Zummo <a.zummo@xxxxxxxxxxxx>"); +MODULE_DESCRIPTION("low-level driver for ep93xx ATA"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(ep93xx_pata_init); +module_exit(ep93xx_pata_exit); -- mfg Manfred Gruber ========================================== Contec Steuerungstechnik & Automation GmbH Manfred Gruber Wildbichler Straße 2e 6341 Ebbs / Austria AUSTRIA ------------------------------------------ http://www.contec.at/ manfred.gruber@xxxxxxxxx phone: 0043 / (0) 5373 / 43143 - 511 fax: 0043 / (0) 5373 / 43143 - 888 ========================================== - To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html