aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_hpt37x.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-11-19 13:10:44 -0500
committerJeff Garzik <jgarzik@redhat.com>2009-12-03 02:46:34 -0500
commit9e87be9edd9114b65a9cf4f93a60b5d9134a972e (patch)
tree73e5dc2e0573de0cb70faf836bd718780a58a530 /drivers/ata/pata_hpt37x.c
parent1b677afda44f7882b7e257d6f025d006ec5d14f9 (diff)
pata_hpt37x: add proper cable detection methods
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/pata_hpt37x.c')
-rw-r--r--drivers/ata/pata_hpt37x.c86
1 files changed, 56 insertions, 30 deletions
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index d0a7df2e5ca..378a8f862e8 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -303,6 +303,59 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
303} 303}
304 304
305/** 305/**
306 * hpt37x_cable_detect - Detect the cable type
307 * @ap: ATA port to detect on
308 *
309 * Return the cable type attached to this port
310 */
311
312static int hpt37x_cable_detect(struct ata_port *ap)
313{
314 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
315 u8 scr2, ata66;
316
317 pci_read_config_byte(pdev, 0x5B, &scr2);
318 pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01);
319 /* Cable register now active */
320 pci_read_config_byte(pdev, 0x5A, &ata66);
321 /* Restore state */
322 pci_write_config_byte(pdev, 0x5B, scr2);
323
324 if (ata66 & (2 >> ap->port_no))
325 return ATA_CBL_PATA40;
326 else
327 return ATA_CBL_PATA80;
328}
329
330/**
331 * hpt374_fn1_cable_detect - Detect the cable type
332 * @ap: ATA port to detect on
333 *
334 * Return the cable type attached to this port
335 */
336
337static int hpt374_fn1_cable_detect(struct ata_port *ap)
338{
339 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
340 unsigned int mcrbase = 0x50 + 4 * ap->port_no;
341 u16 mcr3;
342 u8 ata66;
343
344 /* Do the extra channel work */
345 pci_read_config_word(pdev, mcrbase + 2, &mcr3);
346 /* Set bit 15 of 0x52 to enable TCBLID as input */
347 pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000);
348 pci_read_config_byte(pdev, 0x5A, &ata66);
349 /* Reset TCBLID/FCBLID to output */
350 pci_write_config_word(pdev, mcrbase + 2, mcr3);
351
352 if (ata66 & (2 >> ap->port_no))
353 return ATA_CBL_PATA40;
354 else
355 return ATA_CBL_PATA80;
356}
357
358/**
306 * hpt37x_pre_reset - reset the hpt37x bus 359 * hpt37x_pre_reset - reset the hpt37x bus
307 * @link: ATA link to reset 360 * @link: ATA link to reset
308 * @deadline: deadline jiffies for the operation 361 * @deadline: deadline jiffies for the operation
@@ -312,7 +365,6 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
312 365
313static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) 366static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
314{ 367{
315 u8 scr2, ata66;
316 struct ata_port *ap = link->ap; 368 struct ata_port *ap = link->ap;
317 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 369 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
318 static const struct pci_bits hpt37x_enable_bits[] = { 370 static const struct pci_bits hpt37x_enable_bits[] = {
@@ -322,18 +374,6 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
322 if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) 374 if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
323 return -ENOENT; 375 return -ENOENT;
324 376
325 pci_read_config_byte(pdev, 0x5B, &scr2);
326 pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01);
327 /* Cable register now active */
328 pci_read_config_byte(pdev, 0x5A, &ata66);
329 /* Restore state */
330 pci_write_config_byte(pdev, 0x5B, scr2);
331
332 if (ata66 & (2 >> ap->port_no))
333 ap->cbl = ATA_CBL_PATA40;
334 else
335 ap->cbl = ATA_CBL_PATA80;
336
337 /* Reset the state machine */ 377 /* Reset the state machine */
338 pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); 378 pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
339 udelay(100); 379 udelay(100);
@@ -347,29 +387,12 @@ static int hpt374_fn1_pre_reset(struct ata_link *link, unsigned long deadline)
347 { 0x50, 1, 0x04, 0x04 }, 387 { 0x50, 1, 0x04, 0x04 },
348 { 0x54, 1, 0x04, 0x04 } 388 { 0x54, 1, 0x04, 0x04 }
349 }; 389 };
350 u16 mcr3;
351 u8 ata66;
352 struct ata_port *ap = link->ap; 390 struct ata_port *ap = link->ap;
353 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 391 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
354 unsigned int mcrbase = 0x50 + 4 * ap->port_no;
355 392
356 if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) 393 if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
357 return -ENOENT; 394 return -ENOENT;
358 395
359 /* Do the extra channel work */
360 pci_read_config_word(pdev, mcrbase + 2, &mcr3);
361 /* Set bit 15 of 0x52 to enable TCBLID as input
362 */
363 pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000);
364 pci_read_config_byte(pdev, 0x5A, &ata66);
365 /* Reset TCBLID/FCBLID to output */
366 pci_write_config_word(pdev, mcrbase + 2, mcr3);
367
368 if (ata66 & (2 >> ap->port_no))
369 ap->cbl = ATA_CBL_PATA40;
370 else
371 ap->cbl = ATA_CBL_PATA80;
372
373 /* Reset the state machine */ 396 /* Reset the state machine */
374 pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); 397 pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
375 udelay(100); 398 udelay(100);
@@ -584,6 +607,7 @@ static struct ata_port_operations hpt370_port_ops = {
584 .bmdma_stop = hpt370_bmdma_stop, 607 .bmdma_stop = hpt370_bmdma_stop,
585 608
586 .mode_filter = hpt370_filter, 609 .mode_filter = hpt370_filter,
610 .cable_detect = hpt37x_cable_detect,
587 .set_piomode = hpt370_set_piomode, 611 .set_piomode = hpt370_set_piomode,
588 .set_dmamode = hpt370_set_dmamode, 612 .set_dmamode = hpt370_set_dmamode,
589 .prereset = hpt37x_pre_reset, 613 .prereset = hpt37x_pre_reset,
@@ -608,6 +632,7 @@ static struct ata_port_operations hpt372_port_ops = {
608 632
609 .bmdma_stop = hpt37x_bmdma_stop, 633 .bmdma_stop = hpt37x_bmdma_stop,
610 634
635 .cable_detect = hpt37x_cable_detect,
611 .set_piomode = hpt372_set_piomode, 636 .set_piomode = hpt372_set_piomode,
612 .set_dmamode = hpt372_set_dmamode, 637 .set_dmamode = hpt372_set_dmamode,
613 .prereset = hpt37x_pre_reset, 638 .prereset = hpt37x_pre_reset,
@@ -620,6 +645,7 @@ static struct ata_port_operations hpt372_port_ops = {
620 645
621static struct ata_port_operations hpt374_fn1_port_ops = { 646static struct ata_port_operations hpt374_fn1_port_ops = {
622 .inherits = &hpt372_port_ops, 647 .inherits = &hpt372_port_ops,
648 .cable_detect = hpt374_fn1_cable_detect,
623 .prereset = hpt374_fn1_pre_reset, 649 .prereset = hpt374_fn1_pre_reset,
624}; 650};
625 651