mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	pata_legacy: resychronize with upstream changes and resubmit
Update the legacy driver so it can handle VLB ports nicely, and has an internal structure for nailing new ISA/VLB forms in. Anyone got an ALI14xx and a spare day ;) Also adds an "all" parameter so you can load this driver after all the PCI ones in a boot time kernel and tell it to grab anything ST412 compatible even if it is an unknown PCI device. That allows libata to offer the same "just get me a disk somehow" fallback that old IDE did. Obsoletes pata_qdi. Signed-off-by: Alan Cox <alan@redhat.com> Cc: Tejun Heo <htejun@gmail.com> Cc: Jeff Garzik <jeff@garzik.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
		
							parent
							
								
									c294f1b329
								
							
						
					
					
						commit
						defc9cd826
					
				
					 1 changed files with 607 additions and 147 deletions
				
			
		| 
						 | 
					@ -68,8 +68,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NR_HOST 6
 | 
					#define NR_HOST 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
 | 
					static int all;
 | 
				
			||||||
static int legacy_irq[NR_HOST] = { 14, 15, 11, 10, 8, 12 };
 | 
					module_param(all, int, 0444);
 | 
				
			||||||
 | 
					MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct legacy_data {
 | 
					struct legacy_data {
 | 
				
			||||||
	unsigned long timing;
 | 
						unsigned long timing;
 | 
				
			||||||
| 
						 | 
					@ -80,20 +81,102 @@ struct legacy_data {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum controller {
 | 
				
			||||||
 | 
						BIOS = 0,
 | 
				
			||||||
 | 
						SNOOP = 1,
 | 
				
			||||||
 | 
						PDC20230 = 2,
 | 
				
			||||||
 | 
						HT6560A = 3,
 | 
				
			||||||
 | 
						HT6560B = 4,
 | 
				
			||||||
 | 
						OPTI611A = 5,
 | 
				
			||||||
 | 
						OPTI46X = 6,
 | 
				
			||||||
 | 
						QDI6500 = 7,
 | 
				
			||||||
 | 
						QDI6580 = 8,
 | 
				
			||||||
 | 
						QDI6580DP = 9,		/* Dual channel mode is different */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UNKNOWN = -1
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct legacy_probe {
 | 
				
			||||||
 | 
						unsigned char *name;
 | 
				
			||||||
 | 
						unsigned long port;
 | 
				
			||||||
 | 
						unsigned int irq;
 | 
				
			||||||
 | 
						unsigned int slot;
 | 
				
			||||||
 | 
						enum controller type;
 | 
				
			||||||
 | 
						unsigned long private;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct legacy_controller {
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
 | 
						struct ata_port_operations *ops;
 | 
				
			||||||
 | 
						unsigned int pio_mask;
 | 
				
			||||||
 | 
						unsigned int flags;
 | 
				
			||||||
 | 
						int (*setup)(struct legacy_probe *probe, struct legacy_data *data);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct legacy_probe probe_list[NR_HOST];
 | 
				
			||||||
static struct legacy_data legacy_data[NR_HOST];
 | 
					static struct legacy_data legacy_data[NR_HOST];
 | 
				
			||||||
static struct ata_host *legacy_host[NR_HOST];
 | 
					static struct ata_host *legacy_host[NR_HOST];
 | 
				
			||||||
static int nr_legacy_host;
 | 
					static int nr_legacy_host;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int probe_all;		/* Set to check all ISA port ranges */
 | 
					static int probe_all;		/* Set to check all ISA port ranges */
 | 
				
			||||||
static int ht6560a;			/* HT 6560A on primary 1, secondary 2, both 3 */
 | 
					static int ht6560a;		/* HT 6560A on primary 1, second 2, both 3 */
 | 
				
			||||||
static int ht6560b;			/* HT 6560A on primary 1, secondary 2, both 3 */
 | 
					static int ht6560b;		/* HT 6560A on primary 1, second 2, both 3 */
 | 
				
			||||||
static int opti82c611a;			/* Opti82c611A on primary 1, secondary 2, both 3 */
 | 
					static int opti82c611a;		/* Opti82c611A on primary 1, sec 2, both 3 */
 | 
				
			||||||
static int opti82c46x;			/* Opti 82c465MV present (pri/sec autodetect) */
 | 
					static int opti82c46x;		/* Opti 82c465MV present(pri/sec autodetect) */
 | 
				
			||||||
 | 
					static int qdi;			/* Set to probe QDI controllers */
 | 
				
			||||||
static int autospeed;		/* Chip present which snoops speed changes */
 | 
					static int autospeed;		/* Chip present which snoops speed changes */
 | 
				
			||||||
static int pio_mask = 0x1F;	/* PIO range for autospeed devices */
 | 
					static int pio_mask = 0x1F;	/* PIO range for autospeed devices */
 | 
				
			||||||
static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
 | 
					static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *	legacy_probe_add	-	Add interface to probe list
 | 
				
			||||||
 | 
					 *	@port: Controller port
 | 
				
			||||||
 | 
					 *	@irq: IRQ number
 | 
				
			||||||
 | 
					 *	@type: Controller type
 | 
				
			||||||
 | 
					 *	@private: Controller specific info
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	Add an entry into the probe list for ATA controllers. This is used
 | 
				
			||||||
 | 
					 *	to add the default ISA slots and then to build up the table
 | 
				
			||||||
 | 
					 *	further according to other ISA/VLB/Weird device scans
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	An I/O port list is used to keep ordering stable and sane, as we
 | 
				
			||||||
 | 
					 *	don't have any good way to talk about ordering otherwise
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int legacy_probe_add(unsigned long port, unsigned int irq,
 | 
				
			||||||
 | 
									enum controller type, unsigned long private)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct legacy_probe *lp = &probe_list[0];
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						struct legacy_probe *free = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < NR_HOST; i++) {
 | 
				
			||||||
 | 
							if (lp->port == 0 && free == NULL)
 | 
				
			||||||
 | 
								free = lp;
 | 
				
			||||||
 | 
							/* Matching port, or the correct slot for ordering */
 | 
				
			||||||
 | 
							if (lp->port == port || legacy_port[i] == port) {
 | 
				
			||||||
 | 
								free = lp;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							lp++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (free == NULL) {
 | 
				
			||||||
 | 
							printk(KERN_ERR "pata_legacy: Too many interfaces.\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* Fill in the entry for later probing */
 | 
				
			||||||
 | 
						free->port = port;
 | 
				
			||||||
 | 
						free->irq = irq;
 | 
				
			||||||
 | 
						free->type = type;
 | 
				
			||||||
 | 
						free->private = private;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *	legacy_set_mode		-	mode setting
 | 
					 *	legacy_set_mode		-	mode setting
 | 
				
			||||||
 *	@link: IDE link
 | 
					 *	@link: IDE link
 | 
				
			||||||
| 
						 | 
					@ -113,7 +196,8 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ata_link_for_each_dev(dev, link) {
 | 
						ata_link_for_each_dev(dev, link) {
 | 
				
			||||||
		if (ata_dev_enabled(dev)) {
 | 
							if (ata_dev_enabled(dev)) {
 | 
				
			||||||
			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
 | 
								ata_dev_printk(dev, KERN_INFO,
 | 
				
			||||||
 | 
											"configured for PIO\n");
 | 
				
			||||||
			dev->pio_mode = XFER_PIO_0;
 | 
								dev->pio_mode = XFER_PIO_0;
 | 
				
			||||||
			dev->xfer_mode = XFER_PIO_0;
 | 
								dev->xfer_mode = XFER_PIO_0;
 | 
				
			||||||
			dev->xfer_shift = ATA_SHIFT_PIO;
 | 
								dev->xfer_shift = ATA_SHIFT_PIO;
 | 
				
			||||||
| 
						 | 
					@ -171,7 +255,7 @@ static struct ata_port_operations simple_port_ops = {
 | 
				
			||||||
	.irq_clear	= ata_bmdma_irq_clear,
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
	.irq_on		= ata_irq_on,
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.port_start	= ata_port_start,
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct ata_port_operations legacy_port_ops = {
 | 
					static struct ata_port_operations legacy_port_ops = {
 | 
				
			||||||
| 
						 | 
					@ -198,15 +282,16 @@ static struct ata_port_operations legacy_port_ops = {
 | 
				
			||||||
	.irq_clear	= ata_bmdma_irq_clear,
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
	.irq_on		= ata_irq_on,
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.port_start	= ata_port_start,
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Promise 20230C and 20620 support
 | 
					 *	Promise 20230C and 20620 support
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	This controller supports PIO0 to PIO2. We set PIO timings conservatively to
 | 
					 *	This controller supports PIO0 to PIO2. We set PIO timings
 | 
				
			||||||
 *	allow for 50MHz Vesa Local Bus. The 20620 DMA support is weird being DMA to
 | 
					 *	conservatively to allow for 50MHz Vesa Local Bus. The 20620 DMA
 | 
				
			||||||
 *	controller and PIO'd to the host and not supported.
 | 
					 *	support is weird being DMA to controller and PIO'd to the host
 | 
				
			||||||
 | 
					 *	and not supported.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
					static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
| 
						 | 
					@ -221,8 +306,7 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
	local_irq_save(flags);
 | 
						local_irq_save(flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Unlock the control interface */
 | 
						/* Unlock the control interface */
 | 
				
			||||||
	do
 | 
						do {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		inb(0x1F5);
 | 
							inb(0x1F5);
 | 
				
			||||||
		outb(inb(0x1F2) | 0x80, 0x1F2);
 | 
							outb(inb(0x1F2) | 0x80, 0x1F2);
 | 
				
			||||||
		inb(0x1F2);
 | 
							inb(0x1F2);
 | 
				
			||||||
| 
						 | 
					@ -231,7 +315,7 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
		inb(0x1F2);
 | 
							inb(0x1F2);
 | 
				
			||||||
		inb(0x1F2);
 | 
							inb(0x1F2);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	while((inb(0x1F2) & 0x80) && --tries);
 | 
						while ((inb(0x1F2) & 0x80) && --tries);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local_irq_restore(flags);
 | 
						local_irq_restore(flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -312,14 +396,14 @@ static struct ata_port_operations pdc20230_port_ops = {
 | 
				
			||||||
	.irq_clear	= ata_bmdma_irq_clear,
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
	.irq_on		= ata_irq_on,
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.port_start	= ata_port_start,
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Holtek 6560A support
 | 
					 *	Holtek 6560A support
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	This controller supports PIO0 to PIO2 (no IORDY even though higher timings
 | 
					 *	This controller supports PIO0 to PIO2 (no IORDY even though higher
 | 
				
			||||||
 *	can be loaded).
 | 
					 *	timings can be loaded).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
					static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
| 
						 | 
					@ -366,14 +450,14 @@ static struct ata_port_operations ht6560a_port_ops = {
 | 
				
			||||||
	.irq_clear	= ata_bmdma_irq_clear,
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
	.irq_on		= ata_irq_on,
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.port_start	= ata_port_start,
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Holtek 6560B support
 | 
					 *	Holtek 6560B support
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO setting
 | 
					 *	This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO
 | 
				
			||||||
 *	unless we see an ATAPI device in which case we force it off.
 | 
					 *	setting unless we see an ATAPI device in which case we force it off.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	FIXME: need to implement 2nd channel support.
 | 
					 *	FIXME: need to implement 2nd channel support.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -400,7 +484,7 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
	if (adev->class != ATA_DEV_ATA) {
 | 
						if (adev->class != ATA_DEV_ATA) {
 | 
				
			||||||
		u8 rconf = inb(0x3E6);
 | 
							u8 rconf = inb(0x3E6);
 | 
				
			||||||
		if (rconf & 0x24) {
 | 
							if (rconf & 0x24) {
 | 
				
			||||||
			rconf &= ~ 0x24;
 | 
								rconf &= ~0x24;
 | 
				
			||||||
			outb(rconf, 0x3E6);
 | 
								outb(rconf, 0x3E6);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -431,7 +515,7 @@ static struct ata_port_operations ht6560b_port_ops = {
 | 
				
			||||||
	.irq_clear	= ata_bmdma_irq_clear,
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
	.irq_on		= ata_irq_on,
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.port_start	= ata_port_start,
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -464,7 +548,8 @@ static u8 opti_syscfg(u8 reg)
 | 
				
			||||||
 *	This controller supports PIO0 to PIO3.
 | 
					 *	This controller supports PIO0 to PIO3.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void opti82c611a_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
					static void opti82c611a_set_piomode(struct ata_port *ap,
 | 
				
			||||||
 | 
											struct ata_device *adev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u8 active, recover, setup;
 | 
						u8 active, recover, setup;
 | 
				
			||||||
	struct ata_timing t;
 | 
						struct ata_timing t;
 | 
				
			||||||
| 
						 | 
					@ -551,7 +636,7 @@ static struct ata_port_operations opti82c611a_port_ops = {
 | 
				
			||||||
	.irq_clear	= ata_bmdma_irq_clear,
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
	.irq_on		= ata_irq_on,
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.port_start	= ata_port_start,
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -683,77 +768,282 @@ static struct ata_port_operations opti82c46x_port_ops = {
 | 
				
			||||||
	.irq_clear	= ata_bmdma_irq_clear,
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
	.irq_on		= ata_irq_on,
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.port_start	= ata_port_start,
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ata_timing t;
 | 
				
			||||||
 | 
						struct legacy_data *qdi = ap->host->private_data;
 | 
				
			||||||
 | 
						int active, recovery;
 | 
				
			||||||
 | 
						u8 timing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Get the timing data in cycles */
 | 
				
			||||||
 | 
						ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (qdi->fast) {
 | 
				
			||||||
 | 
							active = 8 - FIT(t.active, 1, 8);
 | 
				
			||||||
 | 
							recovery = 18 - FIT(t.recover, 3, 18);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							active = 9 - FIT(t.active, 2, 9);
 | 
				
			||||||
 | 
							recovery = 15 - FIT(t.recover, 0, 15);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						timing = (recovery << 4) | active | 0x08;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qdi->clock[adev->devno] = timing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						outb(timing, qdi->timing);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *	legacy_init_one		-	attach a legacy interface
 | 
					 *	qdi6580dp_set_piomode		-	PIO setup for dual channel
 | 
				
			||||||
 *	@port: port number
 | 
					 *	@ap: Port
 | 
				
			||||||
 *	@io: I/O port start
 | 
					 *	@adev: Device
 | 
				
			||||||
 *	@ctrl: control port
 | 
					 | 
				
			||||||
 *	@irq: interrupt line
 | 
					 *	@irq: interrupt line
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Register an ISA bus IDE interface. Such interfaces are PIO and we
 | 
					 *	In dual channel mode the 6580 has one clock per channel and we have
 | 
				
			||||||
 *	assume do not support IRQ sharing.
 | 
					 *	to software clockswitch in qc_issue_prot.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl, int irq)
 | 
					static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct legacy_data *ld = &legacy_data[nr_legacy_host];
 | 
						struct ata_timing t;
 | 
				
			||||||
	struct ata_host *host;
 | 
						struct legacy_data *qdi = ap->host->private_data;
 | 
				
			||||||
	struct ata_port *ap;
 | 
						int active, recovery;
 | 
				
			||||||
	struct platform_device *pdev;
 | 
						u8 timing;
 | 
				
			||||||
	struct ata_port_operations *ops = &legacy_port_ops;
 | 
					 | 
				
			||||||
	void __iomem *io_addr, *ctrl_addr;
 | 
					 | 
				
			||||||
	int pio_modes = pio_mask;
 | 
					 | 
				
			||||||
	u32 mask = (1 << port);
 | 
					 | 
				
			||||||
	u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0);
 | 
						/* Get the timing data in cycles */
 | 
				
			||||||
	if (IS_ERR(pdev))
 | 
						ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
 | 
				
			||||||
		return PTR_ERR(pdev);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = -EBUSY;
 | 
						if (qdi->fast) {
 | 
				
			||||||
	if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
 | 
							active = 8 - FIT(t.active, 1, 8);
 | 
				
			||||||
	    devm_request_region(&pdev->dev, ctrl, 1, "pata_legacy") == NULL)
 | 
							recovery = 18 - FIT(t.recover, 3, 18);
 | 
				
			||||||
		goto fail;
 | 
						} else {
 | 
				
			||||||
 | 
							active = 9 - FIT(t.active, 2, 9);
 | 
				
			||||||
	ret = -ENOMEM;
 | 
							recovery = 15 - FIT(t.recover, 0, 15);
 | 
				
			||||||
	io_addr = devm_ioport_map(&pdev->dev, io, 8);
 | 
					 | 
				
			||||||
	ctrl_addr = devm_ioport_map(&pdev->dev, ctrl, 1);
 | 
					 | 
				
			||||||
	if (!io_addr || !ctrl_addr)
 | 
					 | 
				
			||||||
		goto fail;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ht6560a & mask) {
 | 
					 | 
				
			||||||
		ops = &ht6560a_port_ops;
 | 
					 | 
				
			||||||
		pio_modes = 0x07;
 | 
					 | 
				
			||||||
		iordy = ATA_FLAG_NO_IORDY;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (ht6560b & mask) {
 | 
					 | 
				
			||||||
		ops = &ht6560b_port_ops;
 | 
					 | 
				
			||||||
		pio_modes = 0x1F;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (opti82c611a & mask) {
 | 
					 | 
				
			||||||
		ops = &opti82c611a_port_ops;
 | 
					 | 
				
			||||||
		pio_modes = 0x0F;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (opti82c46x & mask) {
 | 
					 | 
				
			||||||
		ops = &opti82c46x_port_ops;
 | 
					 | 
				
			||||||
		pio_modes = 0x0F;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						timing = (recovery << 4) | active | 0x08;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Probe for automatically detectable controllers */
 | 
						qdi->clock[adev->devno] = timing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (io == 0x1F0 && ops == &legacy_port_ops) {
 | 
						outb(timing, qdi->timing + 2 * ap->port_no);
 | 
				
			||||||
 | 
						/* Clear the FIFO */
 | 
				
			||||||
 | 
						if (adev->class != ATA_DEV_ATA)
 | 
				
			||||||
 | 
							outb(0x5F, qdi->timing + 3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *	qdi6580_set_piomode		-	PIO setup for single channel
 | 
				
			||||||
 | 
					 *	@ap: Port
 | 
				
			||||||
 | 
					 *	@adev: Device
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	In single channel mode the 6580 has one clock per device and we can
 | 
				
			||||||
 | 
					 *	avoid the requirement to clock switch. We also have to load the timing
 | 
				
			||||||
 | 
					 *	into the right clock according to whether we are master or slave.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ata_timing t;
 | 
				
			||||||
 | 
						struct legacy_data *qdi = ap->host->private_data;
 | 
				
			||||||
 | 
						int active, recovery;
 | 
				
			||||||
 | 
						u8 timing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Get the timing data in cycles */
 | 
				
			||||||
 | 
						ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (qdi->fast) {
 | 
				
			||||||
 | 
							active = 8 - FIT(t.active, 1, 8);
 | 
				
			||||||
 | 
							recovery = 18 - FIT(t.recover, 3, 18);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							active = 9 - FIT(t.active, 2, 9);
 | 
				
			||||||
 | 
							recovery = 15 - FIT(t.recover, 0, 15);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						timing = (recovery << 4) | active | 0x08;
 | 
				
			||||||
 | 
						qdi->clock[adev->devno] = timing;
 | 
				
			||||||
 | 
						outb(timing, qdi->timing + 2 * adev->devno);
 | 
				
			||||||
 | 
						/* Clear the FIFO */
 | 
				
			||||||
 | 
						if (adev->class != ATA_DEV_ATA)
 | 
				
			||||||
 | 
							outb(0x5F, qdi->timing + 3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *	qdi_qc_issue_prot	-	command issue
 | 
				
			||||||
 | 
					 *	@qc: command pending
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	Called when the libata layer is about to issue a command. We wrap
 | 
				
			||||||
 | 
					 *	this interface so that we can load the correct ATA timings.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ata_port *ap = qc->ap;
 | 
				
			||||||
 | 
						struct ata_device *adev = qc->dev;
 | 
				
			||||||
 | 
						struct legacy_data *qdi = ap->host->private_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (qdi->clock[adev->devno] != qdi->last) {
 | 
				
			||||||
 | 
							if (adev->pio_mode) {
 | 
				
			||||||
 | 
								qdi->last = qdi->clock[adev->devno];
 | 
				
			||||||
 | 
								outb(qdi->clock[adev->devno], qdi->timing +
 | 
				
			||||||
 | 
												2 * ap->port_no);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ata_qc_issue_prot(qc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* For the 6580 can we flip the FIFO on/off at this point ? */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned int qdi_data_xfer(struct ata_device *adev, unsigned char *buf,
 | 
				
			||||||
 | 
										unsigned int buflen, int rw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ata_port *ap = adev->link->ap;
 | 
				
			||||||
 | 
						int slop = buflen & 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ata_id_has_dword_io(adev->id)) {
 | 
				
			||||||
 | 
							if (rw == WRITE)
 | 
				
			||||||
 | 
								iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (unlikely(slop)) {
 | 
				
			||||||
 | 
								u32 pad;
 | 
				
			||||||
 | 
								if (rw == WRITE) {
 | 
				
			||||||
 | 
									memcpy(&pad, buf + buflen - slop, slop);
 | 
				
			||||||
 | 
									pad = le32_to_cpu(pad);
 | 
				
			||||||
 | 
									iowrite32(pad, ap->ioaddr.data_addr);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									pad = ioread32(ap->ioaddr.data_addr);
 | 
				
			||||||
 | 
									pad = cpu_to_le32(pad);
 | 
				
			||||||
 | 
									memcpy(buf + buflen - slop, &pad, slop);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return (buflen + 3) & ~3;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							return ata_data_xfer(adev, buf, buflen, rw);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ata_port_operations qdi6500_port_ops = {
 | 
				
			||||||
 | 
						.set_piomode	= qdi6500_set_piomode,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.qc_prep 	= ata_qc_prep,
 | 
				
			||||||
 | 
						.qc_issue	= qdi_qc_issue_prot,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.data_xfer	= qdi_data_xfer,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.irq_handler	= ata_interrupt,
 | 
				
			||||||
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ata_port_operations qdi6580_port_ops = {
 | 
				
			||||||
 | 
						.set_piomode	= qdi6580_set_piomode,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.qc_prep 	= ata_qc_prep,
 | 
				
			||||||
 | 
						.qc_issue	= ata_qc_issue_prot,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.data_xfer	= qdi_data_xfer,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.irq_handler	= ata_interrupt,
 | 
				
			||||||
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct ata_port_operations qdi6580dp_port_ops = {
 | 
				
			||||||
 | 
						.set_piomode	= qdi6580dp_set_piomode,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.qc_prep 	= ata_qc_prep,
 | 
				
			||||||
 | 
						.qc_issue	= qdi_qc_issue_prot,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.data_xfer	= qdi_data_xfer,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.irq_handler	= ata_interrupt,
 | 
				
			||||||
 | 
						.irq_clear	= ata_bmdma_irq_clear,
 | 
				
			||||||
 | 
						.irq_on		= ata_irq_on,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.port_start	= ata_sff_port_start,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct legacy_controller controllers[] = {
 | 
				
			||||||
 | 
						{"BIOS",	&legacy_port_ops, 	0x1F,
 | 
				
			||||||
 | 
											ATA_FLAG_NO_IORDY,	NULL },
 | 
				
			||||||
 | 
						{"Snooping", 	&simple_port_ops, 	0x1F,
 | 
				
			||||||
 | 
											0	       ,	NULL },
 | 
				
			||||||
 | 
						{"PDC20230",	&pdc20230_port_ops,	0x7,
 | 
				
			||||||
 | 
											ATA_FLAG_NO_IORDY,	NULL },
 | 
				
			||||||
 | 
						{"HT6560A",	&ht6560a_port_ops,	0x07,
 | 
				
			||||||
 | 
											ATA_FLAG_NO_IORDY,	NULL },
 | 
				
			||||||
 | 
						{"HT6560B",	&ht6560b_port_ops,	0x1F,
 | 
				
			||||||
 | 
											ATA_FLAG_NO_IORDY,	NULL },
 | 
				
			||||||
 | 
						{"OPTI82C611A",	&opti82c611a_port_ops,	0x0F,
 | 
				
			||||||
 | 
											0	       ,	NULL },
 | 
				
			||||||
 | 
						{"OPTI82C46X",	&opti82c46x_port_ops,	0x0F,
 | 
				
			||||||
 | 
											0	       ,	NULL },
 | 
				
			||||||
 | 
						{"QDI6500",	&qdi6500_port_ops,	0x07,
 | 
				
			||||||
 | 
											ATA_FLAG_NO_IORDY,	NULL },
 | 
				
			||||||
 | 
						{"QDI6580",	&qdi6580_port_ops,	0x1F,
 | 
				
			||||||
 | 
											0	       ,	NULL },
 | 
				
			||||||
 | 
						{"QDI6580DP",	&qdi6580dp_port_ops,	0x1F,
 | 
				
			||||||
 | 
											0	       ,	NULL }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *	probe_chip_type		-	Discover controller
 | 
				
			||||||
 | 
					 *	@probe: Probe entry to check
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	Probe an ATA port and identify the type of controller. We don't
 | 
				
			||||||
 | 
					 *	check if the controller appears to be driveless at this point.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int probe_chip_type(struct legacy_probe *probe)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int mask = 1 << probe->slot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (probe->port == 0x1F0) {
 | 
				
			||||||
		unsigned long flags;
 | 
							unsigned long flags;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		local_irq_save(flags);
 | 
							local_irq_save(flags);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Probes */
 | 
							/* Probes */
 | 
				
			||||||
		inb(0x1F5);
 | 
					 | 
				
			||||||
		outb(inb(0x1F2) | 0x80, 0x1F2);
 | 
							outb(inb(0x1F2) | 0x80, 0x1F2);
 | 
				
			||||||
 | 
							inb(0x1F5);
 | 
				
			||||||
		inb(0x1F2);
 | 
							inb(0x1F2);
 | 
				
			||||||
		inb(0x3F6);
 | 
							inb(0x3F6);
 | 
				
			||||||
		inb(0x3F6);
 | 
							inb(0x3F6);
 | 
				
			||||||
| 
						 | 
					@ -762,29 +1052,83 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((inb(0x1F2) & 0x80) == 0) {
 | 
							if ((inb(0x1F2) & 0x80) == 0) {
 | 
				
			||||||
			/* PDC20230c or 20630 ? */
 | 
								/* PDC20230c or 20630 ? */
 | 
				
			||||||
			printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n");
 | 
								printk(KERN_INFO  "PDC20230-C/20630 VLB ATA controller"
 | 
				
			||||||
				pio_modes = 0x07;
 | 
												" detected.\n");
 | 
				
			||||||
			ops = &pdc20230_port_ops;
 | 
					 | 
				
			||||||
			iordy = ATA_FLAG_NO_IORDY;
 | 
					 | 
				
			||||||
			udelay(100);
 | 
								udelay(100);
 | 
				
			||||||
			inb(0x1F5);
 | 
								inb(0x1F5);
 | 
				
			||||||
 | 
								local_irq_restore(flags);
 | 
				
			||||||
 | 
								return PDC20230;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			outb(0x55, 0x1F2);
 | 
								outb(0x55, 0x1F2);
 | 
				
			||||||
			inb(0x1F2);
 | 
								inb(0x1F2);
 | 
				
			||||||
			inb(0x1F2);
 | 
								inb(0x1F2);
 | 
				
			||||||
			if (inb(0x1F2) == 0x00) {
 | 
								if (inb(0x1F2) == 0x00)
 | 
				
			||||||
				printk(KERN_INFO "PDC20230-B VLB ATA controller detected.\n");
 | 
									printk(KERN_INFO "PDC20230-B VLB ATA "
 | 
				
			||||||
			}
 | 
											     "controller detected.\n");
 | 
				
			||||||
 | 
								local_irq_restore(flags);
 | 
				
			||||||
 | 
								return BIOS;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		local_irq_restore(flags);
 | 
							local_irq_restore(flags);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ht6560a & mask)
 | 
				
			||||||
 | 
							return HT6560A;
 | 
				
			||||||
 | 
						if (ht6560b & mask)
 | 
				
			||||||
 | 
							return HT6560B;
 | 
				
			||||||
 | 
						if (opti82c611a & mask)
 | 
				
			||||||
 | 
							return OPTI611A;
 | 
				
			||||||
 | 
						if (opti82c46x & mask)
 | 
				
			||||||
 | 
							return OPTI46X;
 | 
				
			||||||
 | 
						if (autospeed & mask)
 | 
				
			||||||
 | 
							return SNOOP;
 | 
				
			||||||
 | 
						return BIOS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Chip does mode setting by command snooping */
 | 
					
 | 
				
			||||||
	if (ops == &legacy_port_ops && (autospeed & mask))
 | 
					/**
 | 
				
			||||||
		ops = &simple_port_ops;
 | 
					 *	legacy_init_one		-	attach a legacy interface
 | 
				
			||||||
 | 
					 *	@pl: probe record
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	Register an ISA bus IDE interface. Such interfaces are PIO and we
 | 
				
			||||||
 | 
					 *	assume do not support IRQ sharing.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __init int legacy_init_one(struct legacy_probe *probe)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct legacy_controller *controller = &controllers[probe->type];
 | 
				
			||||||
 | 
						int pio_modes = controller->pio_mask;
 | 
				
			||||||
 | 
						unsigned long io = probe->port;
 | 
				
			||||||
 | 
						u32 mask = (1 << probe->slot);
 | 
				
			||||||
 | 
						struct ata_port_operations *ops = controller->ops;
 | 
				
			||||||
 | 
						struct legacy_data *ld = &legacy_data[probe->slot];
 | 
				
			||||||
 | 
						struct ata_host *host = NULL;
 | 
				
			||||||
 | 
						struct ata_port *ap;
 | 
				
			||||||
 | 
						struct platform_device *pdev;
 | 
				
			||||||
 | 
						struct ata_device *dev;
 | 
				
			||||||
 | 
						void __iomem *io_addr, *ctrl_addr;
 | 
				
			||||||
 | 
						u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iordy |= controller->flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pdev = platform_device_register_simple(DRV_NAME, probe->slot, NULL, 0);
 | 
				
			||||||
 | 
						if (IS_ERR(pdev))
 | 
				
			||||||
 | 
							return PTR_ERR(pdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = -EBUSY;
 | 
				
			||||||
 | 
						if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
 | 
				
			||||||
 | 
						    devm_request_region(&pdev->dev, io + 0x0206, 1,
 | 
				
			||||||
 | 
												"pata_legacy") == NULL)
 | 
				
			||||||
 | 
							goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = -ENOMEM;
 | 
						ret = -ENOMEM;
 | 
				
			||||||
 | 
						io_addr = devm_ioport_map(&pdev->dev, io, 8);
 | 
				
			||||||
 | 
						ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);
 | 
				
			||||||
 | 
						if (!io_addr || !ctrl_addr)
 | 
				
			||||||
 | 
							goto fail;
 | 
				
			||||||
 | 
						if (controller->setup)
 | 
				
			||||||
 | 
							if (controller->setup(probe, ld) < 0)
 | 
				
			||||||
 | 
								goto fail;
 | 
				
			||||||
	host = ata_host_alloc(&pdev->dev, 1);
 | 
						host = ata_host_alloc(&pdev->dev, 1);
 | 
				
			||||||
	if (!host)
 | 
						if (!host)
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
| 
						 | 
					@ -799,17 +1143,30 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
 | 
				
			||||||
	ata_std_ports(&ap->ioaddr);
 | 
						ata_std_ports(&ap->ioaddr);
 | 
				
			||||||
	ap->private_data = ld;
 | 
						ap->private_data = ld;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, ctrl);
 | 
						ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = ata_host_activate(host, irq, ata_interrupt, 0, &legacy_sht);
 | 
						ret = ata_host_activate(host, probe->irq, ata_interrupt, 0,
 | 
				
			||||||
 | 
													&legacy_sht);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
 | 
						ld->platform_dev = pdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	legacy_host[nr_legacy_host++] = dev_get_drvdata(&pdev->dev);
 | 
						/* Nothing found means we drop the port as its probably not there */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = -ENODEV;
 | 
				
			||||||
 | 
						ata_link_for_each_dev(dev, &ap->link) {
 | 
				
			||||||
 | 
							if (!ata_dev_absent(dev)) {
 | 
				
			||||||
 | 
								legacy_host[probe->slot] = host;
 | 
				
			||||||
			ld->platform_dev = pdev;
 | 
								ld->platform_dev = pdev;
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
 | 
						if (host)
 | 
				
			||||||
 | 
							ata_host_detach(host);
 | 
				
			||||||
 | 
						/* FIXME: use devm for this */
 | 
				
			||||||
 | 
						if (ld->timing)
 | 
				
			||||||
 | 
							release_region(ld->timing, 2);
 | 
				
			||||||
	platform_device_unregister(pdev);
 | 
						platform_device_unregister(pdev);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -820,13 +1177,15 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
 | 
				
			||||||
 *	@master: set this if we find an ATA master
 | 
					 *	@master: set this if we find an ATA master
 | 
				
			||||||
 *	@master: set this if we find an ATA secondary
 | 
					 *	@master: set this if we find an ATA secondary
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	A small number of vendors implemented early PCI ATA interfaces on bridge logic
 | 
					 *	A small number of vendors implemented early PCI ATA interfaces
 | 
				
			||||||
 *	without the ATA interface being PCI visible. Where we have a matching PCI driver
 | 
					 *	on bridge logic without the ATA interface being PCI visible.
 | 
				
			||||||
 *	we must skip the relevant device here. If we don't know about it then the legacy
 | 
					 *	Where we have a matching PCI driver we must skip the relevant
 | 
				
			||||||
 *	driver is the right driver anyway.
 | 
					 *	device here. If we don't know about it then the legacy driver
 | 
				
			||||||
 | 
					 *	is the right driver anyway.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *secondary)
 | 
					static void legacy_check_special_cases(struct pci_dev *p, int *primary,
 | 
				
			||||||
 | 
													int *secondary)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */
 | 
						/* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */
 | 
				
			||||||
	if (p->vendor == 0x1078 && p->device == 0x0000) {
 | 
						if (p->vendor == 0x1078 && p->device == 0x0000) {
 | 
				
			||||||
| 
						 | 
					@ -842,7 +1201,8 @@ static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *sec
 | 
				
			||||||
	if (p->vendor == 0x8086 && p->device == 0x1234) {
 | 
						if (p->vendor == 0x8086 && p->device == 0x1234) {
 | 
				
			||||||
		u16 r;
 | 
							u16 r;
 | 
				
			||||||
		pci_read_config_word(p, 0x6C, &r);
 | 
							pci_read_config_word(p, 0x6C, &r);
 | 
				
			||||||
		if (r & 0x8000) {	/* ATA port enabled */
 | 
							if (r & 0x8000) {
 | 
				
			||||||
 | 
								/* ATA port enabled */
 | 
				
			||||||
			if (r & 0x4000)
 | 
								if (r & 0x4000)
 | 
				
			||||||
				*secondary = 1;
 | 
									*secondary = 1;
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
| 
						 | 
					@ -852,6 +1212,117 @@ static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *sec
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __init void probe_opti_vlb(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* If an OPTI 82C46X is present find out where the channels are */
 | 
				
			||||||
 | 
						static const char *optis[4] = {
 | 
				
			||||||
 | 
							"3/463MV", "5MV",
 | 
				
			||||||
 | 
							"5MVA", "5MVB"
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						u8 chans = 1;
 | 
				
			||||||
 | 
						u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opti82c46x = 3;	/* Assume master and slave first */
 | 
				
			||||||
 | 
						printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n",
 | 
				
			||||||
 | 
													optis[ctrl]);
 | 
				
			||||||
 | 
						if (ctrl == 3)
 | 
				
			||||||
 | 
							chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
 | 
				
			||||||
 | 
						ctrl = opti_syscfg(0xAC);
 | 
				
			||||||
 | 
						/* Check enabled and this port is the 465MV port. On the
 | 
				
			||||||
 | 
						   MVB we may have two channels */
 | 
				
			||||||
 | 
						if (ctrl & 8) {
 | 
				
			||||||
 | 
							if (chans == 2) {
 | 
				
			||||||
 | 
								legacy_probe_add(0x1F0, 14, OPTI46X, 0);
 | 
				
			||||||
 | 
								legacy_probe_add(0x170, 15, OPTI46X, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (ctrl & 4)
 | 
				
			||||||
 | 
								legacy_probe_add(0x170, 15, OPTI46X, 0);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								legacy_probe_add(0x1F0, 14, OPTI46X, 0);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							legacy_probe_add(0x1F0, 14, OPTI46X, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __init void qdi65_identify_port(u8 r, u8 res, unsigned long port)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const unsigned long ide_port[2] = { 0x170, 0x1F0 };
 | 
				
			||||||
 | 
						/* Check card type */
 | 
				
			||||||
 | 
						if ((r & 0xF0) == 0xC0) {
 | 
				
			||||||
 | 
							/* QD6500: single channel */
 | 
				
			||||||
 | 
							if (r & 8) {
 | 
				
			||||||
 | 
								/* Disabled ? */
 | 
				
			||||||
 | 
								release_region(port, 2);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
 | 
				
			||||||
 | 
													QDI6500, port);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
 | 
				
			||||||
 | 
							/* QD6580: dual channel */
 | 
				
			||||||
 | 
							if (!request_region(port + 2 , 2, "pata_qdi")) {
 | 
				
			||||||
 | 
								release_region(port, 2);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							res = inb(port + 3);
 | 
				
			||||||
 | 
							/* Single channel mode ? */
 | 
				
			||||||
 | 
							if (res & 1)
 | 
				
			||||||
 | 
								legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
 | 
				
			||||||
 | 
													QDI6580, port);
 | 
				
			||||||
 | 
							else { /* Dual channel mode */
 | 
				
			||||||
 | 
								legacy_probe_add(0x1F0, 14, QDI6580DP, port);
 | 
				
			||||||
 | 
								/* port + 0x02, r & 0x04 */
 | 
				
			||||||
 | 
								legacy_probe_add(0x170, 15, QDI6580DP, port + 2);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __init void probe_qdi_vlb(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						static const unsigned long qd_port[2] = { 0x30, 0xB0 };
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 *	Check each possible QD65xx base address
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 2; i++) {
 | 
				
			||||||
 | 
							unsigned long port = qd_port[i];
 | 
				
			||||||
 | 
							u8 r, res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (request_region(port, 2, "pata_qdi")) {
 | 
				
			||||||
 | 
								/* Check for a card */
 | 
				
			||||||
 | 
								local_irq_save(flags);
 | 
				
			||||||
 | 
								/* I have no h/w that needs this delay but it
 | 
				
			||||||
 | 
								   is present in the historic code */
 | 
				
			||||||
 | 
								r = inb(port);
 | 
				
			||||||
 | 
								udelay(1);
 | 
				
			||||||
 | 
								outb(0x19, port);
 | 
				
			||||||
 | 
								udelay(1);
 | 
				
			||||||
 | 
								res = inb(port);
 | 
				
			||||||
 | 
								udelay(1);
 | 
				
			||||||
 | 
								outb(r, port);
 | 
				
			||||||
 | 
								udelay(1);
 | 
				
			||||||
 | 
								local_irq_restore(flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* Fail */
 | 
				
			||||||
 | 
								if (res == 0x19) {
 | 
				
			||||||
 | 
									release_region(port, 2);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								/* Passes the presence test */
 | 
				
			||||||
 | 
								r = inb(port + 1);
 | 
				
			||||||
 | 
								udelay(1);
 | 
				
			||||||
 | 
								/* Check port agrees with port set */
 | 
				
			||||||
 | 
								if ((r & 2) >> 1 != i) {
 | 
				
			||||||
 | 
									release_region(port, 2);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								qdi65_identify_port(r, res, port);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *	legacy_init		-	attach legacy interfaces
 | 
					 *	legacy_init		-	attach legacy interfaces
 | 
				
			||||||
| 
						 | 
					@ -869,15 +1340,17 @@ static __init int legacy_init(void)
 | 
				
			||||||
	int ct = 0;
 | 
						int ct = 0;
 | 
				
			||||||
	int primary = 0;
 | 
						int primary = 0;
 | 
				
			||||||
	int secondary = 0;
 | 
						int secondary = 0;
 | 
				
			||||||
	int last_port = NR_HOST;
 | 
						int pci_present = 0;
 | 
				
			||||||
 | 
						struct legacy_probe *pl = &probe_list[0];
 | 
				
			||||||
 | 
						int slot = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct pci_dev *p = NULL;
 | 
						struct pci_dev *p = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_pci_dev(p) {
 | 
						for_each_pci_dev(p) {
 | 
				
			||||||
		int r;
 | 
							int r;
 | 
				
			||||||
		/* Check for any overlap of the system ATA mappings. Native mode controllers
 | 
							/* Check for any overlap of the system ATA mappings. Native
 | 
				
			||||||
		   stuck on these addresses or some devices in 'raid' mode won't be found by
 | 
							   mode controllers stuck on these addresses or some devices
 | 
				
			||||||
		   the storage class test */
 | 
							   in 'raid' mode won't be found by the storage class test */
 | 
				
			||||||
		for (r = 0; r < 6; r++) {
 | 
							for (r = 0; r < 6; r++) {
 | 
				
			||||||
			if (pci_resource_start(p, r) == 0x1f0)
 | 
								if (pci_resource_start(p, r) == 0x1f0)
 | 
				
			||||||
				primary = 1;
 | 
									primary = 1;
 | 
				
			||||||
| 
						 | 
					@ -887,49 +1360,37 @@ static __init int legacy_init(void)
 | 
				
			||||||
		/* Check for special cases */
 | 
							/* Check for special cases */
 | 
				
			||||||
		legacy_check_special_cases(p, &primary, &secondary);
 | 
							legacy_check_special_cases(p, &primary, &secondary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* If PCI bus is present then don't probe for tertiary legacy ports */
 | 
							/* If PCI bus is present then don't probe for tertiary
 | 
				
			||||||
		if (probe_all == 0)
 | 
							   legacy ports */
 | 
				
			||||||
			last_port = 2;
 | 
							pci_present = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If an OPTI 82C46X is present find out where the channels are */
 | 
						if (primary == 0 || all)
 | 
				
			||||||
	if (opti82c46x) {
 | 
							legacy_probe_add(0x1F0, 14, UNKNOWN, 0);
 | 
				
			||||||
		static const char *optis[4] = {
 | 
						if (secondary == 0 || all)
 | 
				
			||||||
			"3/463MV", "5MV",
 | 
							legacy_probe_add(0x170, 15, UNKNOWN, 0);
 | 
				
			||||||
			"5MVA", "5MVB"
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		u8 chans = 1;
 | 
					 | 
				
			||||||
		u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		opti82c46x = 3;	/* Assume master and slave first */
 | 
						if (probe_all || !pci_present) {
 | 
				
			||||||
		printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n", optis[ctrl]);
 | 
							/* ISA/VLB extra ports */
 | 
				
			||||||
		if (ctrl == 3)
 | 
							legacy_probe_add(0x1E8, 11, UNKNOWN, 0);
 | 
				
			||||||
			chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
 | 
							legacy_probe_add(0x168, 10, UNKNOWN, 0);
 | 
				
			||||||
		ctrl = opti_syscfg(0xAC);
 | 
							legacy_probe_add(0x1E0, 8, UNKNOWN, 0);
 | 
				
			||||||
		/* Check enabled and this port is the 465MV port. On the
 | 
							legacy_probe_add(0x160, 12, UNKNOWN, 0);
 | 
				
			||||||
		   MVB we may have two channels */
 | 
					 | 
				
			||||||
		if (ctrl & 8) {
 | 
					 | 
				
			||||||
			if (ctrl & 4)
 | 
					 | 
				
			||||||
				opti82c46x = 2;	/* Slave */
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				opti82c46x = 1;	/* Master */
 | 
					 | 
				
			||||||
			if (chans == 2)
 | 
					 | 
				
			||||||
				opti82c46x = 3; /* Master and Slave */
 | 
					 | 
				
			||||||
		}	/* Slave only */
 | 
					 | 
				
			||||||
		else if (chans == 1)
 | 
					 | 
				
			||||||
			opti82c46x = 1;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < last_port; i++) {
 | 
						if (opti82c46x)
 | 
				
			||||||
		/* Skip primary if we have seen a PCI one */
 | 
							probe_opti_vlb();
 | 
				
			||||||
		if (i == 0 && primary == 1)
 | 
						if (qdi)
 | 
				
			||||||
 | 
							probe_qdi_vlb();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < NR_HOST; i++, pl++) {
 | 
				
			||||||
 | 
							if (pl->port == 0)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		/* Skip secondary if we have seen a PCI one */
 | 
							if (pl->type == UNKNOWN)
 | 
				
			||||||
		if (i == 1 && secondary == 1)
 | 
								pl->type = probe_chip_type(pl);
 | 
				
			||||||
			continue;
 | 
							pl->slot = slot++;
 | 
				
			||||||
		if (legacy_init_one(i, legacy_port[i],
 | 
							if (legacy_init_one(pl) == 0)
 | 
				
			||||||
				   legacy_port[i] + 0x0206,
 | 
					 | 
				
			||||||
				   legacy_irq[i]) == 0)
 | 
					 | 
				
			||||||
			ct++;
 | 
								ct++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (ct != 0)
 | 
						if (ct != 0)
 | 
				
			||||||
| 
						 | 
					@ -943,7 +1404,6 @@ static __exit void legacy_exit(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < nr_legacy_host; i++) {
 | 
						for (i = 0; i < nr_legacy_host; i++) {
 | 
				
			||||||
		struct legacy_data *ld = &legacy_data[i];
 | 
							struct legacy_data *ld = &legacy_data[i];
 | 
				
			||||||
 | 
					 | 
				
			||||||
		ata_host_detach(legacy_host[i]);
 | 
							ata_host_detach(legacy_host[i]);
 | 
				
			||||||
		platform_device_unregister(ld->platform_dev);
 | 
							platform_device_unregister(ld->platform_dev);
 | 
				
			||||||
		if (ld->timing)
 | 
							if (ld->timing)
 | 
				
			||||||
| 
						 | 
					@ -962,9 +1422,9 @@ module_param(ht6560a, int, 0);
 | 
				
			||||||
module_param(ht6560b, int, 0);
 | 
					module_param(ht6560b, int, 0);
 | 
				
			||||||
module_param(opti82c611a, int, 0);
 | 
					module_param(opti82c611a, int, 0);
 | 
				
			||||||
module_param(opti82c46x, int, 0);
 | 
					module_param(opti82c46x, int, 0);
 | 
				
			||||||
 | 
					module_param(qdi, int, 0);
 | 
				
			||||||
module_param(pio_mask, int, 0);
 | 
					module_param(pio_mask, int, 0);
 | 
				
			||||||
module_param(iordy_mask, int, 0);
 | 
					module_param(iordy_mask, int, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module_init(legacy_init);
 | 
					module_init(legacy_init);
 | 
				
			||||||
module_exit(legacy_exit);
 | 
					module_exit(legacy_exit);
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue