diff options
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r-- | drivers/scsi/libata-core.c | 133 |
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 | ||
4374 | struct ata_probe_ent * | 4380 | struct ata_probe_ent * |
4375 | ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port) | 4381 | ata_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 | ||
4404 | static struct ata_probe_ent * | 4417 | static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info **port, int port_num) |
4405 | ata_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, | |||
4470 | int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, | 4472 | int 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 | } |