diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-11-19 13:10:44 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-12-03 02:46:34 -0500 |
commit | 9e87be9edd9114b65a9cf4f93a60b5d9134a972e (patch) | |
tree | 73e5dc2e0573de0cb70faf836bd718780a58a530 /drivers/ata/pata_hpt37x.c | |
parent | 1b677afda44f7882b7e257d6f025d006ec5d14f9 (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.c | 86 |
1 files changed, 56 insertions, 30 deletions
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index d0a7df2e5ca7..378a8f862e82 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 | |||
312 | static 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 | |||
337 | static 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 | ||
313 | static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) | 366 | static 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 | ||
621 | static struct ata_port_operations hpt374_fn1_port_ops = { | 646 | static 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 | ||