aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_cmd64x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/pata_cmd64x.c')
-rw-r--r--drivers/ata/pata_cmd64x.c125
1 files changed, 110 insertions, 15 deletions
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index f98dffedf4bc..dadfc358ba1c 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.2.5" 34#define DRV_VERSION "0.3.1"
35 35
36/* 36/*
37 * CMD64x specific registers definition. 37 * CMD64x specific registers definition.
@@ -254,17 +254,109 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc)
254} 254}
255 255
256/** 256/**
257 * cmd646r1_dma_stop - DMA stop callback 257 * cmd64x_bmdma_stop - DMA stop callback
258 * @qc: Command in progress 258 * @qc: Command in progress
259 * 259 *
260 * Stub for now while investigating the r1 quirk in the old driver. 260 * Track the completion of live DMA commands and clear the
261 * host->private_data DMA tracking flag as we do.
261 */ 262 */
262 263
263static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc) 264static void cmd64x_bmdma_stop(struct ata_queued_cmd *qc)
264{ 265{
266 struct ata_port *ap = qc->ap;
265 ata_bmdma_stop(qc); 267 ata_bmdma_stop(qc);
268 WARN_ON(ap->host->private_data != ap);
269 ap->host->private_data = NULL;
266} 270}
267 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
279static 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}
309
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 */
326irqreturn_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], &reg);
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}
268static struct scsi_host_template cmd64x_sht = { 360static struct scsi_host_template cmd64x_sht = {
269 ATA_BMDMA_SHT(DRV_NAME), 361 ATA_BMDMA_SHT(DRV_NAME),
270}; 362};
@@ -273,6 +365,8 @@ static const struct ata_port_operations cmd64x_base_ops = {
273 .inherits = &ata_bmdma_port_ops, 365 .inherits = &ata_bmdma_port_ops,
274 .set_piomode = cmd64x_set_piomode, 366 .set_piomode = cmd64x_set_piomode,
275 .set_dmamode = cmd64x_set_dmamode, 367 .set_dmamode = cmd64x_set_dmamode,
368 .bmdma_stop = cmd64x_bmdma_stop,
369 .qc_defer = cmd64x_qc_defer,
276}; 370};
277 371
278static struct ata_port_operations cmd64x_port_ops = { 372static struct ata_port_operations cmd64x_port_ops = {
@@ -282,7 +376,6 @@ static struct ata_port_operations cmd64x_port_ops = {
282 376
283static struct ata_port_operations cmd646r1_port_ops = { 377static struct ata_port_operations cmd646r1_port_ops = {
284 .inherits = &cmd64x_base_ops, 378 .inherits = &cmd64x_base_ops,
285 .bmdma_stop = cmd646r1_bmdma_stop,
286 .cable_detect = ata_cable_40wire, 379 .cable_detect = ata_cable_40wire,
287}; 380};
288 381
@@ -290,12 +383,11 @@ static struct ata_port_operations cmd648_port_ops = {
290 .inherits = &cmd64x_base_ops, 383 .inherits = &cmd64x_base_ops,
291 .bmdma_stop = cmd648_bmdma_stop, 384 .bmdma_stop = cmd648_bmdma_stop,
292 .cable_detect = cmd648_cable_detect, 385 .cable_detect = cmd648_cable_detect,
386 .qc_defer = ata_std_qc_defer
293}; 387};
294 388
295static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 389static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
296{ 390{
297 u32 class_rev;
298
299 static const struct ata_port_info cmd_info[6] = { 391 static const struct ata_port_info cmd_info[6] = {
300 { /* CMD 643 - no UDMA */ 392 { /* CMD 643 - no UDMA */
301 .flags = ATA_FLAG_SLAVE_POSS, 393 .flags = ATA_FLAG_SLAVE_POSS,
@@ -340,40 +432,43 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
340 const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL }; 432 const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
341 u8 mrdmode; 433 u8 mrdmode;
342 int rc; 434 int rc;
435 struct ata_host *host;
343 436
344 rc = pcim_enable_device(pdev); 437 rc = pcim_enable_device(pdev);
345 if (rc) 438 if (rc)
346 return rc; 439 return rc;
347 440
348 pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
349 class_rev &= 0xFF;
350
351 if (id->driver_data == 0) /* 643 */ 441 if (id->driver_data == 0) /* 643 */
352 ata_pci_bmdma_clear_simplex(pdev); 442 ata_pci_bmdma_clear_simplex(pdev);
353 443
354 if (pdev->device == PCI_DEVICE_ID_CMD_646) { 444 if (pdev->device == PCI_DEVICE_ID_CMD_646) {
355 /* Does UDMA work ? */ 445 /* Does UDMA work ? */
356 if (class_rev > 4) 446 if (pdev->revision > 4)
357 ppi[0] = &cmd_info[2]; 447 ppi[0] = &cmd_info[2];
358 /* Early rev with other problems ? */ 448 /* Early rev with other problems ? */
359 else if (class_rev == 1) 449 else if (pdev->revision == 1)
360 ppi[0] = &cmd_info[3]; 450 ppi[0] = &cmd_info[3];
361 } 451 }
362 452
453
363 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); 454 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
364 pci_read_config_byte(pdev, MRDMODE, &mrdmode); 455 pci_read_config_byte(pdev, MRDMODE, &mrdmode);
365 mrdmode &= ~ 0x30; /* IRQ set up */ 456 mrdmode &= ~ 0x30; /* IRQ set up */
366 mrdmode |= 0x02; /* Memory read line enable */ 457 mrdmode |= 0x02; /* Memory read line enable */
367 pci_write_config_byte(pdev, MRDMODE, mrdmode); 458 pci_write_config_byte(pdev, MRDMODE, mrdmode);
368 459
369 /* Force PIO 0 here.. */
370
371 /* PPC specific fixup copied from old driver */ 460 /* PPC specific fixup copied from old driver */
372#ifdef CONFIG_PPC 461#ifdef CONFIG_PPC
373 pci_write_config_byte(pdev, UDIDETCR0, 0xF0); 462 pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
374#endif 463#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;
375 469
376 return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL); 470 pci_set_master(pdev);
471 return ata_pci_sff_activate_host(host, cmd64x_interrupt, &cmd64x_sht);
377} 472}
378 473
379#ifdef CONFIG_PM 474#ifdef CONFIG_PM