Re[2]: porting IDE patches to PATA driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Alan,

Thursday, June 25, 2009, 1:29:58 PM, you wrote:

> It would be useful I think if you posted the current code, and also to
> know if you see the same problem (lost IRQ etc) with ATAPI as well as ATA

I've attached the current driver and reduced set of patches I'm trying
to port. Truly speaking I have very little knowledge about IDE / ATAPI
interfaces and simply try to reproduce the original logic using modern
libata functions. As you can see the new pata driver redefines set_piomode /
set_dmamode to tune chipset and bmdma_start to flush CPU cache. It
works fine in UDMA mode on a newer chipset but I cannot get MW-DMA
working on an older chipset.

The complete patch for the EM85XX architecture can be found at
http://mg35tools.svn.sourceforge.net/viewvc/mg35tools/trunk/sources/linux-2.6/

original 2.4.17 kernel for Sigma EM8500 is published at
http://www.uclinux.org/pub/uClinux/ports/arm/EM8500/

-- 
Best regards,
 Andrei                            mailto:andrei.martynov@xxxxxx

Attachment: em85xx-ide.patch
Description: Binary data

/* ide-jasper.c */

/* jasper specific initialization stuff for ide */

#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/scsi_host.h>
#include <linux/libata.h>
#include <linux/platform_device.h>

#define DRV_NAME	"pata_jasper"
#define DRV_VERSION	"0.1"

#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/quasar.h>

// updated to match stock ide driver firmware 1.5.2
static int jasper_tune_chipset(int slave, u8 speed)
{
	unsigned short reg54, reg58;

	speed = speed & 0xFF;

	printk("jasper_tune_chipset: speed = %02x\n", speed);

	/*unsigned int */reg54 = inw(JASPER_IDE_BASE + IDE_UDMACTL);
	/*unsigned int */reg58 = inw(JASPER_IDE_BASE + IDE_UDMATIM);

	if (speed>=XFER_UDMA_0 && speed<=XFER_UDMA_5) {
		if(slave != 0) {
			reg54 |= 0x2;
			reg58 |= (speed-XFER_UDMA_0)<<4;
		}else {
			reg54 |= 0x1;
			reg58 |= (speed-XFER_UDMA_0);
		}

		if (speed == XFER_UDMA_0) {
			outl(0x11100009 + 0x10C00, JASPER_IDE_BASE + IDE_UDMATIM);
			outl(5, JASPER_IDE_BASE + 0x5C);
		} 
			else if (speed == XFER_UDMA_1)
		{
			outl(0x11110A06, JASPER_IDE_BASE + IDE_UDMATIM);
			outl(3, JASPER_IDE_BASE + 0x5C);
		}
			else 
		{
			outl(0x11100004 + 0x10800, JASPER_IDE_BASE + IDE_UDMATIM);
			outl(2, JASPER_IDE_BASE + 0x5C);
		}
	}
		else
	{
		if (!(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)) {
			if (slave != 0) {
				reg54 &= ~0x2;
			} else {
				reg54 &= ~0x1;
			}
		}
	}
	outl(0x89000110, JASPER_IDE_BASE + 0x44);
	outw(reg54, JASPER_IDE_BASE + IDE_UDMACTL);
	outw(reg58, JASPER_IDE_BASE + IDE_UDMATIM);
	return 0; //ide_config_drive_speed(drive, speed);
}

static void jasper_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
//	int slave = adev->devno;
	jasper_tune_chipset(0/*slave*/, adev->dma_mode);
}

static void jasper_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
//	int slave = adev->devno;
	jasper_tune_chipset(0/*slave*/, adev->pio_mode);
}

// standard is 2 (!)
#define JASPER_ATA_DMA_STATUS		4
// standard is 4
#define JASPER_ATA_DMA_TABLE_OFS	8

static void jasper_bmdma_start(struct ata_queued_cmd *qc)
{
	__asm__(
		"mcr	p15, 0, %0, c7, c10, 0\n"		// write-back data cache
		: : "r" (0)
	);
	ata_bmdma_start(qc);
}

static struct scsi_host_template jasper_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_DUMB_MAX_PRD,
	.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,
	.slave_destroy		= ata_scsi_slave_destroy,
	.bios_param		= ata_std_bios_param,
};

static struct ata_port_operations jasper_port_ops = {
	.set_piomode		= jasper_set_piomode,
	.set_dmamode		= jasper_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,

	.freeze			= ata_bmdma_freeze,
	.thaw			= ata_bmdma_thaw,
	.error_handler		= ata_bmdma_error_handler,
	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
	.cable_detect		= ata_cable_40wire,

	.bmdma_setup		= ata_bmdma_setup,

	.bmdma_start		= jasper_bmdma_start,
	.bmdma_stop		= ata_bmdma_stop,
	.bmdma_status		= ata_bmdma_status,

	.qc_prep		= ata_dumb_qc_prep,
	.qc_issue		= ata_qc_issue_prot,
	.data_xfer		= ata_data_xfer,

	.irq_clear		= ata_bmdma_irq_clear,
	.irq_on			= ata_irq_on,

	.port_start		= ata_port_start/*ata_sff_port_start*/,
};

static int __devinit jasper_atapi_probe(struct platform_device *pdev)
{
	struct ata_host *host;
	struct ata_ioports *ioaddr;

	struct ata_port_info pi = {
		.sht		= &jasper_sht,
		.flags		= ATA_FLAG_SLAVE_POSS,
		.pio_mask	= 0x1f,
		.port_ops	= &jasper_port_ops,
#ifdef CONFIG_JASPER_IDE_UDMA
		.mwdma_mask = 0x07,
		.udma_mask = 0x07,
#endif
	};
	const struct ata_port_info *ppi[] = { &pi, NULL };

	int can_udma;

	int chipsetID = __raw_readl(JASPER_SYSCTRL_BASE + SYSCTRL_CHIP_ID);
	can_udma = chipsetID > 0x8500;
	printk("JASPER PATA (IDE) chipset %x: UDMA is %ssupported\n", chipsetID, can_udma ? "" : "not ");
	//	choose ide over dvd loader (DVD_AV_CONTROL)
	//	write 0x8000 to IDETIM

	outl(/*R1*/ 0xffffff - 0xef0000, /*R0*/ JASPER_PIO0_BASE + PIO_DIR);
	outl(/*R1*/ 0xffffff - 0xef0000, /* R3 */ JASPER_PIO0_BASE + PIO_DATA);
	//	choose ide over dvd loader (DVD_AV_CONTROL)
	outl(0x00, JASPER_DVD_BASE + DVD_AV_CTRL);	//0x00 select IDE over DVD-loader
	outw(0x00, JASPER_IDE_BASE + 0x34);
	outl(0x8400+0xF, JASPER_IDE_BASE + IDE_TIM);

//	ppi[0] = ppi[1] = &pi;
	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1);
	if (!host)
		return -ENOMEM;
	ioaddr = &host->ports[0]->ioaddr;

	ioaddr->cmd_addr = __io(JASPER_IDE_BASE + IDE_PRI_DATA);
	ioaddr->ctl_addr = __io(JASPER_IDE_BASE + IDE_PRI_DEVICE_CONTROL);
	ioaddr->altstatus_addr = __io(JASPER_IDE_BASE + IDE_PRI_DEVICE_CONTROL);
	ioaddr->bmdma_addr = __io(JASPER_IDE_DMA_BASE);

	ata_std_ports(ioaddr); // sets other regs based on cmd_addr

	return ata_host_activate(host, IDE_IRQ, ata_interrupt, IRQF_SHARED,
				 &jasper_sht);
}

/**
 *	jasper_atapi_remove	-	unplug a jasper atapi interface
 *	@pdev: platform device
 *
 *	A jasper atapi device has been unplugged. Perform the needed
 *	cleanup. Also called on module unload for any active devices.
 */
static int __devexit jasper_atapi_remove(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct ata_host *host = dev_get_drvdata(dev);

	ata_host_detach(host);

//	peripheral_free_list(atapi_io_port);

	return 0;
}

static struct platform_driver jasper_atapi_driver = {
	.probe			= jasper_atapi_probe,
	.remove			= __devexit_p(jasper_atapi_remove),
	.driver = {
		.name		= DRV_NAME,
		.owner		= THIS_MODULE,
#ifdef CONFIG_PM
		.suspend	= jasper_atapi_suspend,
		.resume		= jasper_atapi_resume,
#endif
	},
};

static int __init jasper_atapi_init(void)
{
	return platform_driver_register(&jasper_atapi_driver);
}

static void __exit jasper_atapi_exit(void)
{
	platform_driver_unregister(&jasper_atapi_driver);
}

module_init(jasper_atapi_init);
module_exit(jasper_atapi_exit);

MODULE_AUTHOR("Anonymous");
MODULE_DESCRIPTION("JASPER IDE driver");
MODULE_LICENSE("GPL");

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux