diff options
| -rw-r--r-- | drivers/ata/pata_cmd64x.c | 118 |
1 files changed, 9 insertions, 109 deletions
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index dadfc358ba1c..0efb1f58f255 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <linux/libata.h> | 31 | #include <linux/libata.h> |
| 32 | 32 | ||
| 33 | #define DRV_NAME "pata_cmd64x" | 33 | #define DRV_NAME "pata_cmd64x" |
| 34 | #define DRV_VERSION "0.3.1" | 34 | #define DRV_VERSION "0.2.5" |
| 35 | 35 | ||
| 36 | /* | 36 | /* |
| 37 | * CMD64x specific registers definition. | 37 | * CMD64x specific registers definition. |
| @@ -219,7 +219,7 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
| 219 | regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift; | 219 | regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift; |
| 220 | /* Merge the control bits */ | 220 | /* Merge the control bits */ |
| 221 | regU |= 1 << adev->devno; /* UDMA on */ | 221 | regU |= 1 << adev->devno; /* UDMA on */ |
| 222 | if (adev->dma_mode > 2) /* 15nS timing */ | 222 | if (adev->dma_mode > XFER_UDMA_2) /* 15nS timing */ |
| 223 | regU |= 4 << adev->devno; | 223 | regU |= 4 << adev->devno; |
| 224 | } else { | 224 | } else { |
| 225 | regU &= ~ (1 << adev->devno); /* UDMA off */ | 225 | regU &= ~ (1 << adev->devno); /* UDMA off */ |
| @@ -254,109 +254,17 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc) | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | /** | 256 | /** |
| 257 | * cmd64x_bmdma_stop - DMA stop callback | 257 | * cmd646r1_dma_stop - DMA stop callback |
| 258 | * @qc: Command in progress | 258 | * @qc: Command in progress |
| 259 | * | 259 | * |
| 260 | * Track the completion of live DMA commands and clear the | 260 | * Stub for now while investigating the r1 quirk in the old driver. |
| 261 | * host->private_data DMA tracking flag as we do. | ||
| 262 | */ | 261 | */ |
| 263 | 262 | ||
| 264 | static void cmd64x_bmdma_stop(struct ata_queued_cmd *qc) | 263 | static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc) |
| 265 | { | 264 | { |
| 266 | struct ata_port *ap = qc->ap; | ||
| 267 | ata_bmdma_stop(qc); | 265 | ata_bmdma_stop(qc); |
| 268 | WARN_ON(ap->host->private_data != ap); | ||
| 269 | ap->host->private_data = NULL; | ||
| 270 | } | ||
| 271 | |||
| 272 | /** | ||
| 273 | * cmd64x_qc_defer - Defer logic for chip limits | ||
| 274 | * @qc: queued command | ||
| 275 | * | ||
| 276 | * Decide whether we can issue the command. Called under the host lock. | ||
| 277 | */ | ||
| 278 | |||
| 279 | static int cmd64x_qc_defer(struct ata_queued_cmd *qc) | ||
| 280 | { | ||
| 281 | struct ata_host *host = qc->ap->host; | ||
| 282 | struct ata_port *alt = host->ports[1 ^ qc->ap->port_no]; | ||
| 283 | int rc; | ||
| 284 | int dma = 0; | ||
| 285 | |||
| 286 | /* Apply the ATA rules first */ | ||
| 287 | rc = ata_std_qc_defer(qc); | ||
| 288 | if (rc) | ||
| 289 | return rc; | ||
| 290 | |||
| 291 | if (qc->tf.protocol == ATAPI_PROT_DMA || | ||
| 292 | qc->tf.protocol == ATA_PROT_DMA) | ||
| 293 | dma = 1; | ||
| 294 | |||
| 295 | /* If the other port is not live then issue the command */ | ||
| 296 | if (alt == NULL || !alt->qc_active) { | ||
| 297 | if (dma) | ||
| 298 | host->private_data = qc->ap; | ||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | /* If there is a live DMA command then wait */ | ||
| 302 | if (host->private_data != NULL) | ||
| 303 | return ATA_DEFER_PORT; | ||
| 304 | if (dma) | ||
| 305 | /* Cannot overlap our DMA command */ | ||
| 306 | return ATA_DEFER_PORT; | ||
| 307 | return 0; | ||
| 308 | } | 266 | } |
| 309 | 267 | ||
| 310 | /** | ||
| 311 | * cmd64x_interrupt - ATA host interrupt handler | ||
| 312 | * @irq: irq line (unused) | ||
| 313 | * @dev_instance: pointer to our ata_host information structure | ||
| 314 | * | ||
| 315 | * Our interrupt handler for PCI IDE devices. Calls | ||
| 316 | * ata_sff_host_intr() for each port that is flagging an IRQ. We cannot | ||
| 317 | * use the defaults as we need to avoid touching status/altstatus during | ||
| 318 | * a DMA. | ||
| 319 | * | ||
| 320 | * LOCKING: | ||
| 321 | * Obtains host lock during operation. | ||
| 322 | * | ||
| 323 | * RETURNS: | ||
| 324 | * IRQ_NONE or IRQ_HANDLED. | ||
| 325 | */ | ||
| 326 | irqreturn_t cmd64x_interrupt(int irq, void *dev_instance) | ||
| 327 | { | ||
| 328 | struct ata_host *host = dev_instance; | ||
| 329 | struct pci_dev *pdev = to_pci_dev(host->dev); | ||
| 330 | unsigned int i; | ||
| 331 | unsigned int handled = 0; | ||
| 332 | unsigned long flags; | ||
| 333 | static const u8 irq_reg[2] = { CFR, ARTTIM23 }; | ||
| 334 | static const u8 irq_mask[2] = { 1 << 2, 1 << 4 }; | ||
| 335 | |||
| 336 | /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ | ||
| 337 | spin_lock_irqsave(&host->lock, flags); | ||
| 338 | |||
| 339 | for (i = 0; i < host->n_ports; i++) { | ||
| 340 | struct ata_port *ap; | ||
| 341 | u8 reg; | ||
| 342 | |||
| 343 | pci_read_config_byte(pdev, irq_reg[i], ®); | ||
| 344 | ap = host->ports[i]; | ||
| 345 | if (ap && (reg & irq_mask[i]) && | ||
| 346 | !(ap->flags & ATA_FLAG_DISABLED)) { | ||
| 347 | struct ata_queued_cmd *qc; | ||
| 348 | |||
| 349 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | ||
| 350 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) && | ||
| 351 | (qc->flags & ATA_QCFLAG_ACTIVE)) | ||
| 352 | handled |= ata_sff_host_intr(ap, qc); | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 357 | |||
| 358 | return IRQ_RETVAL(handled); | ||
| 359 | } | ||
| 360 | static struct scsi_host_template cmd64x_sht = { | 268 | static struct scsi_host_template cmd64x_sht = { |
| 361 | ATA_BMDMA_SHT(DRV_NAME), | 269 | ATA_BMDMA_SHT(DRV_NAME), |
| 362 | }; | 270 | }; |
| @@ -365,8 +273,6 @@ static const struct ata_port_operations cmd64x_base_ops = { | |||
| 365 | .inherits = &ata_bmdma_port_ops, | 273 | .inherits = &ata_bmdma_port_ops, |
| 366 | .set_piomode = cmd64x_set_piomode, | 274 | .set_piomode = cmd64x_set_piomode, |
| 367 | .set_dmamode = cmd64x_set_dmamode, | 275 | .set_dmamode = cmd64x_set_dmamode, |
| 368 | .bmdma_stop = cmd64x_bmdma_stop, | ||
| 369 | .qc_defer = cmd64x_qc_defer, | ||
| 370 | }; | 276 | }; |
| 371 | 277 | ||
| 372 | static struct ata_port_operations cmd64x_port_ops = { | 278 | static struct ata_port_operations cmd64x_port_ops = { |
| @@ -376,6 +282,7 @@ static struct ata_port_operations cmd64x_port_ops = { | |||
| 376 | 282 | ||
| 377 | static struct ata_port_operations cmd646r1_port_ops = { | 283 | static struct ata_port_operations cmd646r1_port_ops = { |
| 378 | .inherits = &cmd64x_base_ops, | 284 | .inherits = &cmd64x_base_ops, |
| 285 | .bmdma_stop = cmd646r1_bmdma_stop, | ||
| 379 | .cable_detect = ata_cable_40wire, | 286 | .cable_detect = ata_cable_40wire, |
| 380 | }; | 287 | }; |
| 381 | 288 | ||
| @@ -383,7 +290,6 @@ static struct ata_port_operations cmd648_port_ops = { | |||
| 383 | .inherits = &cmd64x_base_ops, | 290 | .inherits = &cmd64x_base_ops, |
| 384 | .bmdma_stop = cmd648_bmdma_stop, | 291 | .bmdma_stop = cmd648_bmdma_stop, |
| 385 | .cable_detect = cmd648_cable_detect, | 292 | .cable_detect = cmd648_cable_detect, |
| 386 | .qc_defer = ata_std_qc_defer | ||
| 387 | }; | 293 | }; |
| 388 | 294 | ||
| 389 | static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | 295 | static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
| @@ -432,7 +338,6 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 432 | const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL }; | 338 | const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL }; |
| 433 | u8 mrdmode; | 339 | u8 mrdmode; |
| 434 | int rc; | 340 | int rc; |
| 435 | struct ata_host *host; | ||
| 436 | 341 | ||
| 437 | rc = pcim_enable_device(pdev); | 342 | rc = pcim_enable_device(pdev); |
| 438 | if (rc) | 343 | if (rc) |
| @@ -450,25 +355,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 450 | ppi[0] = &cmd_info[3]; | 355 | ppi[0] = &cmd_info[3]; |
| 451 | } | 356 | } |
| 452 | 357 | ||
| 453 | |||
| 454 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); | 358 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); |
| 455 | pci_read_config_byte(pdev, MRDMODE, &mrdmode); | 359 | pci_read_config_byte(pdev, MRDMODE, &mrdmode); |
| 456 | mrdmode &= ~ 0x30; /* IRQ set up */ | 360 | mrdmode &= ~ 0x30; /* IRQ set up */ |
| 457 | mrdmode |= 0x02; /* Memory read line enable */ | 361 | mrdmode |= 0x02; /* Memory read line enable */ |
| 458 | pci_write_config_byte(pdev, MRDMODE, mrdmode); | 362 | pci_write_config_byte(pdev, MRDMODE, mrdmode); |
| 459 | 363 | ||
| 364 | /* Force PIO 0 here.. */ | ||
| 365 | |||
| 460 | /* PPC specific fixup copied from old driver */ | 366 | /* PPC specific fixup copied from old driver */ |
| 461 | #ifdef CONFIG_PPC | 367 | #ifdef CONFIG_PPC |
| 462 | pci_write_config_byte(pdev, UDIDETCR0, 0xF0); | 368 | pci_write_config_byte(pdev, UDIDETCR0, 0xF0); |
| 463 | #endif | 369 | #endif |
| 464 | rc = ata_pci_sff_prepare_host(pdev, ppi, &host); | ||
| 465 | if (rc) | ||
| 466 | return rc; | ||
| 467 | /* We use this pointer to track the AP which has DMA running */ | ||
| 468 | host->private_data = NULL; | ||
| 469 | 370 | ||
| 470 | pci_set_master(pdev); | 371 | return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL); |
| 471 | return ata_pci_sff_activate_host(host, cmd64x_interrupt, &cmd64x_sht); | ||
| 472 | } | 372 | } |
| 473 | 373 | ||
| 474 | #ifdef CONFIG_PM | 374 | #ifdef CONFIG_PM |
