diff options
Diffstat (limited to 'drivers/scsi/ata_piix.c')
-rw-r--r-- | drivers/scsi/ata_piix.c | 266 |
1 files changed, 201 insertions, 65 deletions
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 94b1261a259d..a9bb3cb7e89b 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c | |||
@@ -105,9 +105,6 @@ enum { | |||
105 | PIIX_FLAG_SCR = (1 << 26), /* SCR available */ | 105 | PIIX_FLAG_SCR = (1 << 26), /* SCR available */ |
106 | PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ | 106 | PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ |
107 | PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ | 107 | PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ |
108 | PIIX_FLAG_COMBINED = (1 << 29), /* combined mode possible */ | ||
109 | /* ICH6/7 use different scheme for map value */ | ||
110 | PIIX_FLAG_COMBINED_ICH6 = PIIX_FLAG_COMBINED | (1 << 30), | ||
111 | 108 | ||
112 | /* combined mode. if set, PATA is channel 0. | 109 | /* combined mode. if set, PATA is channel 0. |
113 | * if clear, PATA is channel 1. | 110 | * if clear, PATA is channel 1. |
@@ -126,6 +123,8 @@ enum { | |||
126 | ich6_sata = 4, | 123 | ich6_sata = 4, |
127 | ich6_sata_ahci = 5, | 124 | ich6_sata_ahci = 5, |
128 | ich6m_sata_ahci = 6, | 125 | ich6m_sata_ahci = 6, |
126 | ich7m_sata_ahci = 7, | ||
127 | ich8_sata_ahci = 8, | ||
129 | 128 | ||
130 | /* constants for mapping table */ | 129 | /* constants for mapping table */ |
131 | P0 = 0, /* port 0 */ | 130 | P0 = 0, /* port 0 */ |
@@ -141,11 +140,19 @@ enum { | |||
141 | 140 | ||
142 | struct piix_map_db { | 141 | struct piix_map_db { |
143 | const u32 mask; | 142 | const u32 mask; |
143 | const u16 port_enable; | ||
144 | const int present_shift; | ||
144 | const int map[][4]; | 145 | const int map[][4]; |
145 | }; | 146 | }; |
146 | 147 | ||
148 | struct piix_host_priv { | ||
149 | const int *map; | ||
150 | const struct piix_map_db *map_db; | ||
151 | }; | ||
152 | |||
147 | static int piix_init_one (struct pci_dev *pdev, | 153 | static int piix_init_one (struct pci_dev *pdev, |
148 | const struct pci_device_id *ent); | 154 | const struct pci_device_id *ent); |
155 | static void piix_host_stop(struct ata_host_set *host_set); | ||
149 | static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); | 156 | static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); |
150 | static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); | 157 | static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); |
151 | static void piix_pata_error_handler(struct ata_port *ap); | 158 | static void piix_pata_error_handler(struct ata_port *ap); |
@@ -182,15 +189,15 @@ static const struct pci_device_id piix_pci_tbl[] = { | |||
182 | /* 82801GB/GR/GH (ICH7, identical to ICH6) */ | 189 | /* 82801GB/GR/GH (ICH7, identical to ICH6) */ |
183 | { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, | 190 | { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, |
184 | /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ | 191 | /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ |
185 | { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, | 192 | { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7m_sata_ahci }, |
186 | /* Enterprise Southbridge 2 (where's the datasheet?) */ | 193 | /* Enterprise Southbridge 2 (where's the datasheet?) */ |
187 | { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, | 194 | { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, |
188 | /* SATA Controller 1 IDE (ICH8, no datasheet yet) */ | 195 | /* SATA Controller 1 IDE (ICH8, no datasheet yet) */ |
189 | { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, | 196 | { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, |
190 | /* SATA Controller 2 IDE (ICH8, ditto) */ | 197 | /* SATA Controller 2 IDE (ICH8, ditto) */ |
191 | { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, | 198 | { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, |
192 | /* Mobile SATA Controller IDE (ICH8M, ditto) */ | 199 | /* Mobile SATA Controller IDE (ICH8M, ditto) */ |
193 | { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, | 200 | { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, |
194 | 201 | ||
195 | { } /* terminate list */ | 202 | { } /* terminate list */ |
196 | }; | 203 | }; |
@@ -254,7 +261,7 @@ static const struct ata_port_operations piix_pata_ops = { | |||
254 | 261 | ||
255 | .port_start = ata_port_start, | 262 | .port_start = ata_port_start, |
256 | .port_stop = ata_port_stop, | 263 | .port_stop = ata_port_stop, |
257 | .host_stop = ata_host_stop, | 264 | .host_stop = piix_host_stop, |
258 | }; | 265 | }; |
259 | 266 | ||
260 | static const struct ata_port_operations piix_sata_ops = { | 267 | static const struct ata_port_operations piix_sata_ops = { |
@@ -284,11 +291,13 @@ static const struct ata_port_operations piix_sata_ops = { | |||
284 | 291 | ||
285 | .port_start = ata_port_start, | 292 | .port_start = ata_port_start, |
286 | .port_stop = ata_port_stop, | 293 | .port_stop = ata_port_stop, |
287 | .host_stop = ata_host_stop, | 294 | .host_stop = piix_host_stop, |
288 | }; | 295 | }; |
289 | 296 | ||
290 | static struct piix_map_db ich5_map_db = { | 297 | static const struct piix_map_db ich5_map_db = { |
291 | .mask = 0x7, | 298 | .mask = 0x7, |
299 | .port_enable = 0x3, | ||
300 | .present_shift = 4, | ||
292 | .map = { | 301 | .map = { |
293 | /* PM PS SM SS MAP */ | 302 | /* PM PS SM SS MAP */ |
294 | { P0, NA, P1, NA }, /* 000b */ | 303 | { P0, NA, P1, NA }, /* 000b */ |
@@ -302,8 +311,10 @@ static struct piix_map_db ich5_map_db = { | |||
302 | }, | 311 | }, |
303 | }; | 312 | }; |
304 | 313 | ||
305 | static struct piix_map_db ich6_map_db = { | 314 | static const struct piix_map_db ich6_map_db = { |
306 | .mask = 0x3, | 315 | .mask = 0x3, |
316 | .port_enable = 0xf, | ||
317 | .present_shift = 4, | ||
307 | .map = { | 318 | .map = { |
308 | /* PM PS SM SS MAP */ | 319 | /* PM PS SM SS MAP */ |
309 | { P0, P2, P1, P3 }, /* 00b */ | 320 | { P0, P2, P1, P3 }, /* 00b */ |
@@ -313,8 +324,10 @@ static struct piix_map_db ich6_map_db = { | |||
313 | }, | 324 | }, |
314 | }; | 325 | }; |
315 | 326 | ||
316 | static struct piix_map_db ich6m_map_db = { | 327 | static const struct piix_map_db ich6m_map_db = { |
317 | .mask = 0x3, | 328 | .mask = 0x3, |
329 | .port_enable = 0x5, | ||
330 | .present_shift = 4, | ||
318 | .map = { | 331 | .map = { |
319 | /* PM PS SM SS MAP */ | 332 | /* PM PS SM SS MAP */ |
320 | { P0, P2, RV, RV }, /* 00b */ | 333 | { P0, P2, RV, RV }, /* 00b */ |
@@ -324,6 +337,47 @@ static struct piix_map_db ich6m_map_db = { | |||
324 | }, | 337 | }, |
325 | }; | 338 | }; |
326 | 339 | ||
340 | static const struct piix_map_db ich7m_map_db = { | ||
341 | .mask = 0x3, | ||
342 | .port_enable = 0x5, | ||
343 | .present_shift = 4, | ||
344 | |||
345 | /* Map 01b isn't specified in the doc but some notebooks use | ||
346 | * it anyway. ATM, the only case spotted carries subsystem ID | ||
347 | * 1025:0107. This is the only difference from ich6m. | ||
348 | */ | ||
349 | .map = { | ||
350 | /* PM PS SM SS MAP */ | ||
351 | { P0, P2, RV, RV }, /* 00b */ | ||
352 | { IDE, IDE, P1, P3 }, /* 01b */ | ||
353 | { P0, P2, IDE, IDE }, /* 10b */ | ||
354 | { RV, RV, RV, RV }, | ||
355 | }, | ||
356 | }; | ||
357 | |||
358 | static const struct piix_map_db ich8_map_db = { | ||
359 | .mask = 0x3, | ||
360 | .port_enable = 0x3, | ||
361 | .present_shift = 8, | ||
362 | .map = { | ||
363 | /* PM PS SM SS MAP */ | ||
364 | { P0, NA, P1, NA }, /* 00b (hardwired) */ | ||
365 | { RV, RV, RV, RV }, | ||
366 | { RV, RV, RV, RV }, /* 10b (never) */ | ||
367 | { RV, RV, RV, RV }, | ||
368 | }, | ||
369 | }; | ||
370 | |||
371 | static const struct piix_map_db *piix_map_db_table[] = { | ||
372 | [ich5_sata] = &ich5_map_db, | ||
373 | [esb_sata] = &ich5_map_db, | ||
374 | [ich6_sata] = &ich6_map_db, | ||
375 | [ich6_sata_ahci] = &ich6_map_db, | ||
376 | [ich6m_sata_ahci] = &ich6m_map_db, | ||
377 | [ich7m_sata_ahci] = &ich7m_map_db, | ||
378 | [ich8_sata_ahci] = &ich8_map_db, | ||
379 | }; | ||
380 | |||
327 | static struct ata_port_info piix_port_info[] = { | 381 | static struct ata_port_info piix_port_info[] = { |
328 | /* piix4_pata */ | 382 | /* piix4_pata */ |
329 | { | 383 | { |
@@ -356,63 +410,82 @@ static struct ata_port_info piix_port_info[] = { | |||
356 | /* ich5_sata */ | 410 | /* ich5_sata */ |
357 | { | 411 | { |
358 | .sht = &piix_sht, | 412 | .sht = &piix_sht, |
359 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | | 413 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR | |
360 | PIIX_FLAG_CHECKINTR, | 414 | PIIX_FLAG_IGNORE_PCS, |
361 | .pio_mask = 0x1f, /* pio0-4 */ | 415 | .pio_mask = 0x1f, /* pio0-4 */ |
362 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 416 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
363 | .udma_mask = 0x7f, /* udma0-6 */ | 417 | .udma_mask = 0x7f, /* udma0-6 */ |
364 | .port_ops = &piix_sata_ops, | 418 | .port_ops = &piix_sata_ops, |
365 | .private_data = &ich5_map_db, | ||
366 | }, | 419 | }, |
367 | 420 | ||
368 | /* i6300esb_sata */ | 421 | /* i6300esb_sata */ |
369 | { | 422 | { |
370 | .sht = &piix_sht, | 423 | .sht = &piix_sht, |
371 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | | 424 | .host_flags = ATA_FLAG_SATA | |
372 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS, | 425 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS, |
373 | .pio_mask = 0x1f, /* pio0-4 */ | 426 | .pio_mask = 0x1f, /* pio0-4 */ |
374 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 427 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
375 | .udma_mask = 0x7f, /* udma0-6 */ | 428 | .udma_mask = 0x7f, /* udma0-6 */ |
376 | .port_ops = &piix_sata_ops, | 429 | .port_ops = &piix_sata_ops, |
377 | .private_data = &ich5_map_db, | ||
378 | }, | 430 | }, |
379 | 431 | ||
380 | /* ich6_sata */ | 432 | /* ich6_sata */ |
381 | { | 433 | { |
382 | .sht = &piix_sht, | 434 | .sht = &piix_sht, |
383 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | | 435 | .host_flags = ATA_FLAG_SATA | |
384 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR, | 436 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR, |
385 | .pio_mask = 0x1f, /* pio0-4 */ | 437 | .pio_mask = 0x1f, /* pio0-4 */ |
386 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 438 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
387 | .udma_mask = 0x7f, /* udma0-6 */ | 439 | .udma_mask = 0x7f, /* udma0-6 */ |
388 | .port_ops = &piix_sata_ops, | 440 | .port_ops = &piix_sata_ops, |
389 | .private_data = &ich6_map_db, | ||
390 | }, | 441 | }, |
391 | 442 | ||
392 | /* ich6_sata_ahci */ | 443 | /* ich6_sata_ahci */ |
393 | { | 444 | { |
394 | .sht = &piix_sht, | 445 | .sht = &piix_sht, |
395 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | | 446 | .host_flags = ATA_FLAG_SATA | |
396 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | | 447 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | |
397 | PIIX_FLAG_AHCI, | 448 | PIIX_FLAG_AHCI, |
398 | .pio_mask = 0x1f, /* pio0-4 */ | 449 | .pio_mask = 0x1f, /* pio0-4 */ |
399 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 450 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
400 | .udma_mask = 0x7f, /* udma0-6 */ | 451 | .udma_mask = 0x7f, /* udma0-6 */ |
401 | .port_ops = &piix_sata_ops, | 452 | .port_ops = &piix_sata_ops, |
402 | .private_data = &ich6_map_db, | ||
403 | }, | 453 | }, |
404 | 454 | ||
405 | /* ich6m_sata_ahci */ | 455 | /* ich6m_sata_ahci */ |
406 | { | 456 | { |
407 | .sht = &piix_sht, | 457 | .sht = &piix_sht, |
408 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | | 458 | .host_flags = ATA_FLAG_SATA | |
459 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | | ||
460 | PIIX_FLAG_AHCI, | ||
461 | .pio_mask = 0x1f, /* pio0-4 */ | ||
462 | .mwdma_mask = 0x07, /* mwdma0-2 */ | ||
463 | .udma_mask = 0x7f, /* udma0-6 */ | ||
464 | .port_ops = &piix_sata_ops, | ||
465 | }, | ||
466 | |||
467 | /* ich7m_sata_ahci */ | ||
468 | { | ||
469 | .sht = &piix_sht, | ||
470 | .host_flags = ATA_FLAG_SATA | | ||
471 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | | ||
472 | PIIX_FLAG_AHCI, | ||
473 | .pio_mask = 0x1f, /* pio0-4 */ | ||
474 | .mwdma_mask = 0x07, /* mwdma0-2 */ | ||
475 | .udma_mask = 0x7f, /* udma0-6 */ | ||
476 | .port_ops = &piix_sata_ops, | ||
477 | }, | ||
478 | |||
479 | /* ich8_sata_ahci */ | ||
480 | { | ||
481 | .sht = &piix_sht, | ||
482 | .host_flags = ATA_FLAG_SATA | | ||
409 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | | 483 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | |
410 | PIIX_FLAG_AHCI, | 484 | PIIX_FLAG_AHCI, |
411 | .pio_mask = 0x1f, /* pio0-4 */ | 485 | .pio_mask = 0x1f, /* pio0-4 */ |
412 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 486 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
413 | .udma_mask = 0x7f, /* udma0-6 */ | 487 | .udma_mask = 0x7f, /* udma0-6 */ |
414 | .port_ops = &piix_sata_ops, | 488 | .port_ops = &piix_sata_ops, |
415 | .private_data = &ich6m_map_db, | ||
416 | }, | 489 | }, |
417 | }; | 490 | }; |
418 | 491 | ||
@@ -427,6 +500,11 @@ MODULE_LICENSE("GPL"); | |||
427 | MODULE_DEVICE_TABLE(pci, piix_pci_tbl); | 500 | MODULE_DEVICE_TABLE(pci, piix_pci_tbl); |
428 | MODULE_VERSION(DRV_VERSION); | 501 | MODULE_VERSION(DRV_VERSION); |
429 | 502 | ||
503 | static int force_pcs = 0; | ||
504 | module_param(force_pcs, int, 0444); | ||
505 | MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " | ||
506 | "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)"); | ||
507 | |||
430 | /** | 508 | /** |
431 | * piix_pata_cbl_detect - Probe host controller cable detect info | 509 | * piix_pata_cbl_detect - Probe host controller cable detect info |
432 | * @ap: Port for which cable detect info is desired | 510 | * @ap: Port for which cable detect info is desired |
@@ -491,74 +569,83 @@ static void piix_pata_error_handler(struct ata_port *ap) | |||
491 | } | 569 | } |
492 | 570 | ||
493 | /** | 571 | /** |
494 | * piix_sata_prereset - prereset for SATA host controller | 572 | * piix_sata_present_mask - determine present mask for SATA host controller |
495 | * @ap: Target port | 573 | * @ap: Target port |
496 | * | 574 | * |
497 | * Reads and configures SATA PCI device's PCI config register | 575 | * Reads SATA PCI device's PCI config register Port Configuration |
498 | * Port Configuration and Status (PCS) to determine port and | 576 | * and Status (PCS) to determine port and device availability. |
499 | * device availability. Return -ENODEV to skip reset if no | ||
500 | * device is present. | ||
501 | * | 577 | * |
502 | * LOCKING: | 578 | * LOCKING: |
503 | * None (inherited from caller). | 579 | * None (inherited from caller). |
504 | * | 580 | * |
505 | * RETURNS: | 581 | * RETURNS: |
506 | * 0 if device is present, -ENODEV otherwise. | 582 | * determined present_mask |
507 | */ | 583 | */ |
508 | static int piix_sata_prereset(struct ata_port *ap) | 584 | static unsigned int piix_sata_present_mask(struct ata_port *ap) |
509 | { | 585 | { |
510 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); | 586 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); |
511 | const unsigned int *map = ap->host_set->private_data; | 587 | struct piix_host_priv *hpriv = ap->host_set->private_data; |
588 | const unsigned int *map = hpriv->map; | ||
512 | int base = 2 * ap->hard_port_no; | 589 | int base = 2 * ap->hard_port_no; |
513 | unsigned int present_mask = 0; | 590 | unsigned int present_mask = 0; |
514 | int port, i; | 591 | int port, i; |
515 | u8 pcs; | 592 | u16 pcs; |
516 | 593 | ||
517 | pci_read_config_byte(pdev, ICH5_PCS, &pcs); | 594 | pci_read_config_word(pdev, ICH5_PCS, &pcs); |
518 | DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); | 595 | DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); |
519 | 596 | ||
520 | /* enable all ports on this ap and wait for them to settle */ | ||
521 | for (i = 0; i < 2; i++) { | ||
522 | port = map[base + i]; | ||
523 | if (port >= 0) | ||
524 | pcs |= 1 << port; | ||
525 | } | ||
526 | |||
527 | pci_write_config_byte(pdev, ICH5_PCS, pcs); | ||
528 | msleep(100); | ||
529 | |||
530 | /* let's see which devices are present */ | ||
531 | pci_read_config_byte(pdev, ICH5_PCS, &pcs); | ||
532 | |||
533 | for (i = 0; i < 2; i++) { | 597 | for (i = 0; i < 2; i++) { |
534 | port = map[base + i]; | 598 | port = map[base + i]; |
535 | if (port < 0) | 599 | if (port < 0) |
536 | continue; | 600 | continue; |
537 | if (ap->flags & PIIX_FLAG_IGNORE_PCS || pcs & 1 << (4 + port)) | 601 | if ((ap->flags & PIIX_FLAG_IGNORE_PCS) || |
602 | (pcs & 1 << (hpriv->map_db->present_shift + port))) | ||
538 | present_mask |= 1 << i; | 603 | present_mask |= 1 << i; |
539 | else | ||
540 | pcs &= ~(1 << port); | ||
541 | } | 604 | } |
542 | 605 | ||
543 | /* disable offline ports on non-AHCI controllers */ | ||
544 | if (!(ap->flags & PIIX_FLAG_AHCI)) | ||
545 | pci_write_config_byte(pdev, ICH5_PCS, pcs); | ||
546 | |||
547 | DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", | 606 | DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", |
548 | ap->id, pcs, present_mask); | 607 | ap->id, pcs, present_mask); |
549 | 608 | ||
550 | if (!present_mask) { | 609 | return present_mask; |
551 | ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); | 610 | } |
552 | ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; | 611 | |
553 | return 0; | 612 | /** |
613 | * piix_sata_softreset - reset SATA host port via ATA SRST | ||
614 | * @ap: port to reset | ||
615 | * @classes: resulting classes of attached devices | ||
616 | * | ||
617 | * Reset SATA host port via ATA SRST. On controllers with | ||
618 | * reliable PCS present bits, the bits are used to determine | ||
619 | * device presence. | ||
620 | * | ||
621 | * LOCKING: | ||
622 | * Kernel thread context (may sleep) | ||
623 | * | ||
624 | * RETURNS: | ||
625 | * 0 on success, -errno otherwise. | ||
626 | */ | ||
627 | static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes) | ||
628 | { | ||
629 | unsigned int present_mask; | ||
630 | int i, rc; | ||
631 | |||
632 | present_mask = piix_sata_present_mask(ap); | ||
633 | |||
634 | rc = ata_std_softreset(ap, classes); | ||
635 | if (rc) | ||
636 | return rc; | ||
637 | |||
638 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | ||
639 | if (!(present_mask & (1 << i))) | ||
640 | classes[i] = ATA_DEV_NONE; | ||
554 | } | 641 | } |
555 | 642 | ||
556 | return ata_std_prereset(ap); | 643 | return 0; |
557 | } | 644 | } |
558 | 645 | ||
559 | static void piix_sata_error_handler(struct ata_port *ap) | 646 | static void piix_sata_error_handler(struct ata_port *ap) |
560 | { | 647 | { |
561 | ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL, | 648 | ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL, |
562 | ata_std_postreset); | 649 | ata_std_postreset); |
563 | } | 650 | } |
564 | 651 | ||
@@ -761,10 +848,40 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) | |||
761 | return no_piix_dma; | 848 | return no_piix_dma; |
762 | } | 849 | } |
763 | 850 | ||
851 | static void __devinit piix_init_pcs(struct pci_dev *pdev, | ||
852 | struct ata_port_info *pinfo, | ||
853 | const struct piix_map_db *map_db) | ||
854 | { | ||
855 | u16 pcs, new_pcs; | ||
856 | |||
857 | pci_read_config_word(pdev, ICH5_PCS, &pcs); | ||
858 | |||
859 | new_pcs = pcs | map_db->port_enable; | ||
860 | |||
861 | if (new_pcs != pcs) { | ||
862 | DPRINTK("updating PCS from 0x%x to 0x%x\n", pcs, new_pcs); | ||
863 | pci_write_config_word(pdev, ICH5_PCS, new_pcs); | ||
864 | msleep(150); | ||
865 | } | ||
866 | |||
867 | if (force_pcs == 1) { | ||
868 | dev_printk(KERN_INFO, &pdev->dev, | ||
869 | "force ignoring PCS (0x%x)\n", new_pcs); | ||
870 | pinfo[0].host_flags |= PIIX_FLAG_IGNORE_PCS; | ||
871 | pinfo[1].host_flags |= PIIX_FLAG_IGNORE_PCS; | ||
872 | } else if (force_pcs == 2) { | ||
873 | dev_printk(KERN_INFO, &pdev->dev, | ||
874 | "force honoring PCS (0x%x)\n", new_pcs); | ||
875 | pinfo[0].host_flags &= ~PIIX_FLAG_IGNORE_PCS; | ||
876 | pinfo[1].host_flags &= ~PIIX_FLAG_IGNORE_PCS; | ||
877 | } | ||
878 | } | ||
879 | |||
764 | static void __devinit piix_init_sata_map(struct pci_dev *pdev, | 880 | static void __devinit piix_init_sata_map(struct pci_dev *pdev, |
765 | struct ata_port_info *pinfo) | 881 | struct ata_port_info *pinfo, |
882 | const struct piix_map_db *map_db) | ||
766 | { | 883 | { |
767 | struct piix_map_db *map_db = pinfo[0].private_data; | 884 | struct piix_host_priv *hpriv = pinfo[0].private_data; |
768 | const unsigned int *map; | 885 | const unsigned int *map; |
769 | int i, invalid_map = 0; | 886 | int i, invalid_map = 0; |
770 | u8 map_value; | 887 | u8 map_value; |
@@ -788,6 +905,7 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, | |||
788 | case IDE: | 905 | case IDE: |
789 | WARN_ON((i & 1) || map[i + 1] != IDE); | 906 | WARN_ON((i & 1) || map[i + 1] != IDE); |
790 | pinfo[i / 2] = piix_port_info[ich5_pata]; | 907 | pinfo[i / 2] = piix_port_info[ich5_pata]; |
908 | pinfo[i / 2].private_data = hpriv; | ||
791 | i++; | 909 | i++; |
792 | printk(" IDE IDE"); | 910 | printk(" IDE IDE"); |
793 | break; | 911 | break; |
@@ -805,8 +923,8 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, | |||
805 | dev_printk(KERN_ERR, &pdev->dev, | 923 | dev_printk(KERN_ERR, &pdev->dev, |
806 | "invalid MAP value %u\n", map_value); | 924 | "invalid MAP value %u\n", map_value); |
807 | 925 | ||
808 | pinfo[0].private_data = (void *)map; | 926 | hpriv->map = map; |
809 | pinfo[1].private_data = (void *)map; | 927 | hpriv->map_db = map_db; |
810 | } | 928 | } |
811 | 929 | ||
812 | /** | 930 | /** |
@@ -829,6 +947,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
829 | static int printed_version; | 947 | static int printed_version; |
830 | struct ata_port_info port_info[2]; | 948 | struct ata_port_info port_info[2]; |
831 | struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] }; | 949 | struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] }; |
950 | struct piix_host_priv *hpriv; | ||
832 | unsigned long host_flags; | 951 | unsigned long host_flags; |
833 | 952 | ||
834 | if (!printed_version++) | 953 | if (!printed_version++) |
@@ -839,8 +958,14 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
839 | if (!in_module_init) | 958 | if (!in_module_init) |
840 | return -ENODEV; | 959 | return -ENODEV; |
841 | 960 | ||
961 | hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL); | ||
962 | if (!hpriv) | ||
963 | return -ENOMEM; | ||
964 | |||
842 | port_info[0] = piix_port_info[ent->driver_data]; | 965 | port_info[0] = piix_port_info[ent->driver_data]; |
843 | port_info[1] = piix_port_info[ent->driver_data]; | 966 | port_info[1] = piix_port_info[ent->driver_data]; |
967 | port_info[0].private_data = hpriv; | ||
968 | port_info[1].private_data = hpriv; | ||
844 | 969 | ||
845 | host_flags = port_info[0].host_flags; | 970 | host_flags = port_info[0].host_flags; |
846 | 971 | ||
@@ -855,8 +980,12 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
855 | } | 980 | } |
856 | 981 | ||
857 | /* Initialize SATA map */ | 982 | /* Initialize SATA map */ |
858 | if (host_flags & ATA_FLAG_SATA) | 983 | if (host_flags & ATA_FLAG_SATA) { |
859 | piix_init_sata_map(pdev, port_info); | 984 | piix_init_sata_map(pdev, port_info, |
985 | piix_map_db_table[ent->driver_data]); | ||
986 | piix_init_pcs(pdev, port_info, | ||
987 | piix_map_db_table[ent->driver_data]); | ||
988 | } | ||
860 | 989 | ||
861 | /* On ICH5, some BIOSen disable the interrupt using the | 990 | /* On ICH5, some BIOSen disable the interrupt using the |
862 | * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. | 991 | * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. |
@@ -879,6 +1008,13 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
879 | return ata_pci_init_one(pdev, ppinfo, 2); | 1008 | return ata_pci_init_one(pdev, ppinfo, 2); |
880 | } | 1009 | } |
881 | 1010 | ||
1011 | static void piix_host_stop(struct ata_host_set *host_set) | ||
1012 | { | ||
1013 | if (host_set->next == NULL) | ||
1014 | kfree(host_set->private_data); | ||
1015 | ata_host_stop(host_set); | ||
1016 | } | ||
1017 | |||
882 | static int __init piix_init(void) | 1018 | static int __init piix_init(void) |
883 | { | 1019 | { |
884 | int rc; | 1020 | int rc; |