diff options
| author | Tejun Heo <htejun@gmail.com> | 2006-06-17 02:49:56 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-06-20 04:59:22 -0400 |
| commit | 39f8758259868a01ecad29b4379661dd3f21881f (patch) | |
| tree | 12c9583bc5ed11d2c7c4b95b796251d30c465c16 | |
| parent | ada364e884eb7e60ee96e84cbce07b3c90234c9d (diff) | |
[PATCH] sata_nv: convert to new EH
Convert to new EH.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/scsi/sata_nv.c | 115 |
1 files changed, 89 insertions, 26 deletions
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 94cb17903fae..2a1bd85404e0 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c | |||
| @@ -68,6 +68,9 @@ enum { | |||
| 68 | 68 | ||
| 69 | NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ | 69 | NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ |
| 70 | 70 | ||
| 71 | NV_INT_ALL = 0x0f, | ||
| 72 | NV_INT_MASK = NV_INT_DEV, | ||
| 73 | |||
| 71 | /* INT_CONFIG */ | 74 | /* INT_CONFIG */ |
| 72 | NV_INT_CONFIG = 0x12, | 75 | NV_INT_CONFIG = 0x12, |
| 73 | NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI | 76 | NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI |
| @@ -88,6 +91,12 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, | |||
| 88 | static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); | 91 | static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); |
| 89 | static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | 92 | static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); |
| 90 | 93 | ||
| 94 | static void nv_nf2_freeze(struct ata_port *ap); | ||
| 95 | static void nv_nf2_thaw(struct ata_port *ap); | ||
| 96 | static void nv_ck804_freeze(struct ata_port *ap); | ||
| 97 | static void nv_ck804_thaw(struct ata_port *ap); | ||
| 98 | static void nv_error_handler(struct ata_port *ap); | ||
| 99 | |||
| 91 | enum nv_host_type | 100 | enum nv_host_type |
| 92 | { | 101 | { |
| 93 | GENERIC, | 102 | GENERIC, |
| @@ -166,14 +175,16 @@ static const struct ata_port_operations nv_generic_ops = { | |||
| 166 | .exec_command = ata_exec_command, | 175 | .exec_command = ata_exec_command, |
| 167 | .check_status = ata_check_status, | 176 | .check_status = ata_check_status, |
| 168 | .dev_select = ata_std_dev_select, | 177 | .dev_select = ata_std_dev_select, |
| 169 | .phy_reset = sata_phy_reset, | ||
| 170 | .bmdma_setup = ata_bmdma_setup, | 178 | .bmdma_setup = ata_bmdma_setup, |
| 171 | .bmdma_start = ata_bmdma_start, | 179 | .bmdma_start = ata_bmdma_start, |
| 172 | .bmdma_stop = ata_bmdma_stop, | 180 | .bmdma_stop = ata_bmdma_stop, |
| 173 | .bmdma_status = ata_bmdma_status, | 181 | .bmdma_status = ata_bmdma_status, |
| 174 | .qc_prep = ata_qc_prep, | 182 | .qc_prep = ata_qc_prep, |
| 175 | .qc_issue = ata_qc_issue_prot, | 183 | .qc_issue = ata_qc_issue_prot, |
| 176 | .eng_timeout = ata_eng_timeout, | 184 | .freeze = ata_bmdma_freeze, |
| 185 | .thaw = ata_bmdma_thaw, | ||
| 186 | .error_handler = nv_error_handler, | ||
| 187 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
| 177 | .data_xfer = ata_pio_data_xfer, | 188 | .data_xfer = ata_pio_data_xfer, |
| 178 | .irq_handler = nv_generic_interrupt, | 189 | .irq_handler = nv_generic_interrupt, |
| 179 | .irq_clear = ata_bmdma_irq_clear, | 190 | .irq_clear = ata_bmdma_irq_clear, |
| @@ -191,14 +202,16 @@ static const struct ata_port_operations nv_nf2_ops = { | |||
| 191 | .exec_command = ata_exec_command, | 202 | .exec_command = ata_exec_command, |
| 192 | .check_status = ata_check_status, | 203 | .check_status = ata_check_status, |
| 193 | .dev_select = ata_std_dev_select, | 204 | .dev_select = ata_std_dev_select, |
| 194 | .phy_reset = sata_phy_reset, | ||
| 195 | .bmdma_setup = ata_bmdma_setup, | 205 | .bmdma_setup = ata_bmdma_setup, |
| 196 | .bmdma_start = ata_bmdma_start, | 206 | .bmdma_start = ata_bmdma_start, |
| 197 | .bmdma_stop = ata_bmdma_stop, | 207 | .bmdma_stop = ata_bmdma_stop, |
| 198 | .bmdma_status = ata_bmdma_status, | 208 | .bmdma_status = ata_bmdma_status, |
| 199 | .qc_prep = ata_qc_prep, | 209 | .qc_prep = ata_qc_prep, |
| 200 | .qc_issue = ata_qc_issue_prot, | 210 | .qc_issue = ata_qc_issue_prot, |
| 201 | .eng_timeout = ata_eng_timeout, | 211 | .freeze = nv_nf2_freeze, |
| 212 | .thaw = nv_nf2_thaw, | ||
| 213 | .error_handler = nv_error_handler, | ||
| 214 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
| 202 | .data_xfer = ata_pio_data_xfer, | 215 | .data_xfer = ata_pio_data_xfer, |
| 203 | .irq_handler = nv_nf2_interrupt, | 216 | .irq_handler = nv_nf2_interrupt, |
| 204 | .irq_clear = ata_bmdma_irq_clear, | 217 | .irq_clear = ata_bmdma_irq_clear, |
| @@ -216,14 +229,16 @@ static const struct ata_port_operations nv_ck804_ops = { | |||
| 216 | .exec_command = ata_exec_command, | 229 | .exec_command = ata_exec_command, |
| 217 | .check_status = ata_check_status, | 230 | .check_status = ata_check_status, |
| 218 | .dev_select = ata_std_dev_select, | 231 | .dev_select = ata_std_dev_select, |
| 219 | .phy_reset = sata_phy_reset, | ||
| 220 | .bmdma_setup = ata_bmdma_setup, | 232 | .bmdma_setup = ata_bmdma_setup, |
| 221 | .bmdma_start = ata_bmdma_start, | 233 | .bmdma_start = ata_bmdma_start, |
| 222 | .bmdma_stop = ata_bmdma_stop, | 234 | .bmdma_stop = ata_bmdma_stop, |
| 223 | .bmdma_status = ata_bmdma_status, | 235 | .bmdma_status = ata_bmdma_status, |
| 224 | .qc_prep = ata_qc_prep, | 236 | .qc_prep = ata_qc_prep, |
| 225 | .qc_issue = ata_qc_issue_prot, | 237 | .qc_issue = ata_qc_issue_prot, |
| 226 | .eng_timeout = ata_eng_timeout, | 238 | .freeze = nv_ck804_freeze, |
| 239 | .thaw = nv_ck804_thaw, | ||
| 240 | .error_handler = nv_error_handler, | ||
| 241 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
| 227 | .data_xfer = ata_pio_data_xfer, | 242 | .data_xfer = ata_pio_data_xfer, |
| 228 | .irq_handler = nv_ck804_interrupt, | 243 | .irq_handler = nv_ck804_interrupt, |
| 229 | .irq_clear = ata_bmdma_irq_clear, | 244 | .irq_clear = ata_bmdma_irq_clear, |
| @@ -234,22 +249,11 @@ static const struct ata_port_operations nv_ck804_ops = { | |||
| 234 | .host_stop = nv_ck804_host_stop, | 249 | .host_stop = nv_ck804_host_stop, |
| 235 | }; | 250 | }; |
| 236 | 251 | ||
| 237 | /* FIXME: The hardware provides the necessary SATA PHY controls | ||
| 238 | * to support ATA_FLAG_SATA_RESET. However, it is currently | ||
| 239 | * necessary to disable that flag, to solve misdetection problems. | ||
| 240 | * See http://bugme.osdl.org/show_bug.cgi?id=3352 for more info. | ||
| 241 | * | ||
| 242 | * This problem really needs to be investigated further. But in the | ||
| 243 | * meantime, we avoid ATA_FLAG_SATA_RESET to get people working. | ||
| 244 | */ | ||
| 245 | static struct ata_port_info nv_port_info[] = { | 252 | static struct ata_port_info nv_port_info[] = { |
| 246 | /* generic */ | 253 | /* generic */ |
| 247 | { | 254 | { |
| 248 | .sht = &nv_sht, | 255 | .sht = &nv_sht, |
| 249 | .host_flags = ATA_FLAG_SATA | | 256 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
| 250 | /* ATA_FLAG_SATA_RESET | */ | ||
| 251 | ATA_FLAG_SRST | | ||
| 252 | ATA_FLAG_NO_LEGACY, | ||
| 253 | .pio_mask = NV_PIO_MASK, | 257 | .pio_mask = NV_PIO_MASK, |
| 254 | .mwdma_mask = NV_MWDMA_MASK, | 258 | .mwdma_mask = NV_MWDMA_MASK, |
| 255 | .udma_mask = NV_UDMA_MASK, | 259 | .udma_mask = NV_UDMA_MASK, |
| @@ -258,10 +262,7 @@ static struct ata_port_info nv_port_info[] = { | |||
| 258 | /* nforce2/3 */ | 262 | /* nforce2/3 */ |
| 259 | { | 263 | { |
| 260 | .sht = &nv_sht, | 264 | .sht = &nv_sht, |
| 261 | .host_flags = ATA_FLAG_SATA | | 265 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
| 262 | /* ATA_FLAG_SATA_RESET | */ | ||
| 263 | ATA_FLAG_SRST | | ||
| 264 | ATA_FLAG_NO_LEGACY, | ||
| 265 | .pio_mask = NV_PIO_MASK, | 266 | .pio_mask = NV_PIO_MASK, |
| 266 | .mwdma_mask = NV_MWDMA_MASK, | 267 | .mwdma_mask = NV_MWDMA_MASK, |
| 267 | .udma_mask = NV_UDMA_MASK, | 268 | .udma_mask = NV_UDMA_MASK, |
| @@ -270,10 +271,7 @@ static struct ata_port_info nv_port_info[] = { | |||
| 270 | /* ck804 */ | 271 | /* ck804 */ |
| 271 | { | 272 | { |
| 272 | .sht = &nv_sht, | 273 | .sht = &nv_sht, |
| 273 | .host_flags = ATA_FLAG_SATA | | 274 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
| 274 | /* ATA_FLAG_SATA_RESET | */ | ||
| 275 | ATA_FLAG_SRST | | ||
| 276 | ATA_FLAG_NO_LEGACY, | ||
| 277 | .pio_mask = NV_PIO_MASK, | 275 | .pio_mask = NV_PIO_MASK, |
| 278 | .mwdma_mask = NV_MWDMA_MASK, | 276 | .mwdma_mask = NV_MWDMA_MASK, |
| 279 | .udma_mask = NV_UDMA_MASK, | 277 | .udma_mask = NV_UDMA_MASK, |
| @@ -410,6 +408,71 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) | |||
| 410 | iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); | 408 | iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); |
| 411 | } | 409 | } |
| 412 | 410 | ||
| 411 | static void nv_nf2_freeze(struct ata_port *ap) | ||
| 412 | { | ||
| 413 | unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; | ||
| 414 | int shift = ap->port_no * NV_INT_PORT_SHIFT; | ||
| 415 | u8 mask; | ||
| 416 | |||
| 417 | mask = inb(scr_addr + NV_INT_ENABLE); | ||
| 418 | mask &= ~(NV_INT_ALL << shift); | ||
| 419 | outb(mask, scr_addr + NV_INT_ENABLE); | ||
| 420 | } | ||
| 421 | |||
| 422 | static void nv_nf2_thaw(struct ata_port *ap) | ||
| 423 | { | ||
| 424 | unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; | ||
| 425 | int shift = ap->port_no * NV_INT_PORT_SHIFT; | ||
| 426 | u8 mask; | ||
| 427 | |||
| 428 | outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS); | ||
| 429 | |||
| 430 | mask = inb(scr_addr + NV_INT_ENABLE); | ||
| 431 | mask |= (NV_INT_MASK << shift); | ||
| 432 | outb(mask, scr_addr + NV_INT_ENABLE); | ||
| 433 | } | ||
| 434 | |||
| 435 | static void nv_ck804_freeze(struct ata_port *ap) | ||
| 436 | { | ||
| 437 | void __iomem *mmio_base = ap->host_set->mmio_base; | ||
| 438 | int shift = ap->port_no * NV_INT_PORT_SHIFT; | ||
| 439 | u8 mask; | ||
| 440 | |||
| 441 | mask = readb(mmio_base + NV_INT_ENABLE_CK804); | ||
| 442 | mask &= ~(NV_INT_ALL << shift); | ||
| 443 | writeb(mask, mmio_base + NV_INT_ENABLE_CK804); | ||
| 444 | } | ||
| 445 | |||
| 446 | static void nv_ck804_thaw(struct ata_port *ap) | ||
| 447 | { | ||
| 448 | void __iomem *mmio_base = ap->host_set->mmio_base; | ||
| 449 | int shift = ap->port_no * NV_INT_PORT_SHIFT; | ||
| 450 | u8 mask; | ||
| 451 | |||
| 452 | writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804); | ||
| 453 | |||
| 454 | mask = readb(mmio_base + NV_INT_ENABLE_CK804); | ||
| 455 | mask |= (NV_INT_MASK << shift); | ||
| 456 | writeb(mask, mmio_base + NV_INT_ENABLE_CK804); | ||
| 457 | } | ||
| 458 | |||
| 459 | static int nv_hardreset(struct ata_port *ap, unsigned int *class) | ||
| 460 | { | ||
| 461 | unsigned int dummy; | ||
| 462 | |||
| 463 | /* SATA hardreset fails to retrieve proper device signature on | ||
| 464 | * some controllers. Don't classify on hardreset. For more | ||
| 465 | * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 | ||
| 466 | */ | ||
| 467 | return sata_std_hardreset(ap, &dummy); | ||
| 468 | } | ||
| 469 | |||
| 470 | static void nv_error_handler(struct ata_port *ap) | ||
| 471 | { | ||
| 472 | ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, | ||
| 473 | nv_hardreset, ata_std_postreset); | ||
| 474 | } | ||
| 475 | |||
| 413 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | 476 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) |
| 414 | { | 477 | { |
| 415 | static int printed_version = 0; | 478 | static int printed_version = 0; |
