aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2005-10-04 08:09:19 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-04 08:09:19 -0400
commit47a8659380d40d5c0786ddb62a89b3f7f1392430 (patch)
tree696e7f9874e6087e6aaec51fbe1d4a91cd3dfc64 /drivers/scsi/libata-core.c
parentfe998aa7e27f125f6768ec6b137b0ce2c9790509 (diff)
libata: bitmask based pci init functions for one or two ports
This redoes the n_ports logic I proposed before as a bitmask. ata_pci_init_native_mode is now used with a mask allowing for mixed mode stuff later on. ata_pci_init_legacy_port is called with port number and does one port now not two. Instead it is called twice by the ata init logic which cleans both of them up. There are stil limits in the original code left over - IRQ/port mapping for legacy mode should be arch specific values - You can have one legacy mode IDE adapter per PCI root bridge on some systems - Doesn't handle mixed mode devices yet (but is now a lot closer to it)
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c133
1 files changed, 76 insertions, 57 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 03d422e99e58..82ec7f30bf3f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -4363,85 +4363,87 @@ void ata_pci_host_stop (struct ata_host_set *host_set)
4363 * ata_pci_init_native_mode - Initialize native-mode driver 4363 * ata_pci_init_native_mode - Initialize native-mode driver
4364 * @pdev: pci device to be initialized 4364 * @pdev: pci device to be initialized
4365 * @port: array[2] of pointers to port info structures. 4365 * @port: array[2] of pointers to port info structures.
4366 * @ports: bitmap of ports present
4366 * 4367 *
4367 * Utility function which allocates and initializes an 4368 * Utility function which allocates and initializes an
4368 * ata_probe_ent structure for a standard dual-port 4369 * ata_probe_ent structure for a standard dual-port
4369 * PIO-based IDE controller. The returned ata_probe_ent 4370 * PIO-based IDE controller. The returned ata_probe_ent
4370 * structure can be passed to ata_device_add(). The returned 4371 * structure can be passed to ata_device_add(). The returned
4371 * ata_probe_ent structure should then be freed with kfree(). 4372 * ata_probe_ent structure should then be freed with kfree().
4373 *
4374 * The caller need only pass the address of the primary port, the
4375 * secondary will be deduced automatically. If the device has non
4376 * standard secondary port mappings this function can be called twice,
4377 * once for each interface.
4372 */ 4378 */
4373 4379
4374struct ata_probe_ent * 4380struct ata_probe_ent *
4375ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port) 4381ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
4376{ 4382{
4377 struct ata_probe_ent *probe_ent = 4383 struct ata_probe_ent *probe_ent =
4378 ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); 4384 ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
4385 int p = 0;
4386
4379 if (!probe_ent) 4387 if (!probe_ent)
4380 return NULL; 4388 return NULL;
4381 4389
4382 probe_ent->n_ports = 2;
4383 probe_ent->irq = pdev->irq; 4390 probe_ent->irq = pdev->irq;
4384 probe_ent->irq_flags = SA_SHIRQ; 4391 probe_ent->irq_flags = SA_SHIRQ;
4385 4392
4386 probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); 4393 if (ports & ATA_PORT_PRIMARY) {
4387 probe_ent->port[0].altstatus_addr = 4394 probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
4388 probe_ent->port[0].ctl_addr = 4395 probe_ent->port[p].altstatus_addr =
4389 pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; 4396 probe_ent->port[p].ctl_addr =
4390 probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); 4397 pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
4391 4398 probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
4392 probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); 4399 ata_std_ports(&probe_ent->port[p]);
4393 probe_ent->port[1].altstatus_addr = 4400 p++;
4394 probe_ent->port[1].ctl_addr = 4401 }
4395 pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
4396 probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
4397 4402
4398 ata_std_ports(&probe_ent->port[0]); 4403 if (ports & ATA_PORT_SECONDARY) {
4399 ata_std_ports(&probe_ent->port[1]); 4404 probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
4405 probe_ent->port[p].altstatus_addr =
4406 probe_ent->port[p].ctl_addr =
4407 pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
4408 probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
4409 ata_std_ports(&probe_ent->port[p]);
4410 p++;
4411 }
4400 4412
4413 probe_ent->n_ports = p;
4401 return probe_ent; 4414 return probe_ent;
4402} 4415}
4403 4416
4404static struct ata_probe_ent * 4417static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info **port, int port_num)
4405ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
4406 struct ata_probe_ent **ppe2)
4407{ 4418{
4408 struct ata_probe_ent *probe_ent, *probe_ent2; 4419 struct ata_probe_ent *probe_ent;
4409 4420
4410 probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); 4421 probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
4411 if (!probe_ent) 4422 if (!probe_ent)
4412 return NULL; 4423 return NULL;
4413 probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]);
4414 if (!probe_ent2) {
4415 kfree(probe_ent);
4416 return NULL;
4417 }
4418
4419 probe_ent->n_ports = 1;
4420 probe_ent->irq = 14;
4421 4424
4422 probe_ent->hard_port_no = 0; 4425
4423 probe_ent->legacy_mode = 1; 4426 probe_ent->legacy_mode = 1;
4424 4427 probe_ent->n_ports = 1;
4425 probe_ent2->n_ports = 1; 4428 probe_ent->hard_port_no = port_num;
4426 probe_ent2->irq = 15; 4429
4427 4430 switch(port_num)
4428 probe_ent2->hard_port_no = 1; 4431 {
4429 probe_ent2->legacy_mode = 1; 4432 case 0:
4430 4433 probe_ent->irq = 14;
4431 probe_ent->port[0].cmd_addr = 0x1f0; 4434 probe_ent->port[0].cmd_addr = 0x1f0;
4432 probe_ent->port[0].altstatus_addr = 4435 probe_ent->port[0].altstatus_addr =
4433 probe_ent->port[0].ctl_addr = 0x3f6; 4436 probe_ent->port[0].ctl_addr = 0x3f6;
4434 probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); 4437 break;
4435 4438 case 1:
4436 probe_ent2->port[0].cmd_addr = 0x170; 4439 probe_ent->irq = 15;
4437 probe_ent2->port[0].altstatus_addr = 4440 probe_ent->port[0].cmd_addr = 0x170;
4438 probe_ent2->port[0].ctl_addr = 0x376; 4441 probe_ent->port[0].altstatus_addr =
4439 probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8; 4442 probe_ent->port[0].ctl_addr = 0x376;
4440 4443 break;
4444 }
4445 probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4) + 8 * port_num;
4441 ata_std_ports(&probe_ent->port[0]); 4446 ata_std_ports(&probe_ent->port[0]);
4442 ata_std_ports(&probe_ent2->port[0]);
4443
4444 *ppe2 = probe_ent2;
4445 return probe_ent; 4447 return probe_ent;
4446} 4448}
4447 4449
@@ -4470,7 +4472,7 @@ ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
4470int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, 4472int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
4471 unsigned int n_ports) 4473 unsigned int n_ports)
4472{ 4474{
4473 struct ata_probe_ent *probe_ent, *probe_ent2 = NULL; 4475 struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
4474 struct ata_port_info *port[2]; 4476 struct ata_port_info *port[2];
4475 u8 tmp8, mask; 4477 u8 tmp8, mask;
4476 unsigned int legacy_mode = 0; 4478 unsigned int legacy_mode = 0;
@@ -4487,7 +4489,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
4487 4489
4488 if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0 4490 if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
4489 && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { 4491 && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
4490 /* TODO: support transitioning to native mode? */ 4492 /* TODO: What if one channel is in native mode ... */
4491 pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8); 4493 pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
4492 mask = (1 << 2) | (1 << 0); 4494 mask = (1 << 2) | (1 << 0);
4493 if ((tmp8 & mask) != mask) 4495 if ((tmp8 & mask) != mask)
@@ -4495,11 +4497,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
4495 } 4497 }
4496 4498
4497 /* FIXME... */ 4499 /* FIXME... */
4498 if ((!legacy_mode) && (n_ports > 1)) { 4500 if ((!legacy_mode) && (n_ports > 2)) {
4499 printk(KERN_ERR "ata: BUG: native mode, n_ports > 1\n"); 4501 printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
4500 return -EINVAL; 4502 n_ports = 2;
4503 /* For now */
4501 } 4504 }
4502 4505
4506 /* FIXME: Really for ATA it isn't safe because the device may be
4507 multi-purpose and we want to leave it alone if it was already
4508 enabled. Secondly for shared use as Arjan says we want refcounting
4509
4510 Checking dev->is_enabled is insufficient as this is not set at
4511 boot for the primary video which is BIOS enabled
4512 */
4513
4503 rc = pci_enable_device(pdev); 4514 rc = pci_enable_device(pdev);
4504 if (rc) 4515 if (rc)
4505 return rc; 4516 return rc;
@@ -4510,6 +4521,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
4510 goto err_out; 4521 goto err_out;
4511 } 4522 }
4512 4523
4524 /* FIXME: Should use platform specific mappers for legacy port ranges */
4513 if (legacy_mode) { 4525 if (legacy_mode) {
4514 if (!request_region(0x1f0, 8, "libata")) { 4526 if (!request_region(0x1f0, 8, "libata")) {
4515 struct resource *conflict, res; 4527 struct resource *conflict, res;
@@ -4554,10 +4566,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
4554 goto err_out_regions; 4566 goto err_out_regions;
4555 4567
4556 if (legacy_mode) { 4568 if (legacy_mode) {
4557 probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2); 4569 if (legacy_mode & (1 << 0))
4558 } else 4570 probe_ent = ata_pci_init_legacy_port(pdev, port, 0);
4559 probe_ent = ata_pci_init_native_mode(pdev, port); 4571 if (legacy_mode & (1 << 1))
4560 if (!probe_ent) { 4572 probe_ent2 = ata_pci_init_legacy_port(pdev, port, 1);
4573 } else {
4574 if (n_ports == 2)
4575 probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
4576 else
4577 probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
4578 }
4579 if (!probe_ent && !probe_ent2) {
4561 rc = -ENOMEM; 4580 rc = -ENOMEM;
4562 goto err_out_regions; 4581 goto err_out_regions;
4563 } 4582 }