diff options
-rw-r--r-- | sys/dev/ata/ata-pci.c | 15 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.h | 8 | ||||
-rw-r--r-- | sys/dev/ata/ata-sata.c | 177 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-ahci.c | 159 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-intel.c | 2 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-jmicron.c | 28 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-marvell.c | 2 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-nvidia.c | 2 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-promise.c | 4 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-siliconimage.c | 4 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-sis.c | 2 | ||||
-rw-r--r-- | sys/dev/ata/chipsets/ata-via.c | 2 |
12 files changed, 300 insertions, 105 deletions
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 97261d2..5fe26a8 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -584,22 +584,35 @@ ata_pcichannel_detach(device_t dev) static int ata_pcichannel_suspend(device_t dev) { + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); + int error; if (!ch->attached) return (0); - return ata_suspend(dev); + if ((error = ata_suspend(dev))) + return (error); + + if (ctlr->ch_suspend != NULL && (error = ctlr->ch_suspend(dev))) + return (error); + + return (0); } static int ata_pcichannel_resume(device_t dev) { + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); + int error; if (!ch->attached) return (0); + if (ctlr->ch_resume != NULL && (error = ctlr->ch_resume(dev))) + return (error); + return ata_resume(dev); } diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index 27a341e..9e31bc7 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -57,6 +57,8 @@ struct ata_pci_controller { int (*resume)(device_t); int (*ch_attach)(device_t); int (*ch_detach)(device_t); + int (*ch_suspend)(device_t); + int (*ch_resume)(device_t); int (*locking)(device_t, int); void (*reset)(device_t); void (*setmode)(device_t, int); @@ -443,7 +445,9 @@ int ata_mode2idx(int mode); /* global prototypes ata-sata.c */ void ata_sata_phy_check_events(device_t dev); -int ata_sata_phy_reset(device_t dev); +int ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val); +int ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val); +int ata_sata_phy_reset(device_t dev, int port, int quick); void ata_sata_setmode(device_t dev, int mode); int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis); void ata_pm_identify(device_t dev); @@ -452,6 +456,8 @@ void ata_pm_identify(device_t dev); int ata_ahci_chipinit(device_t); int ata_ahci_ch_attach(device_t dev); int ata_ahci_ch_detach(device_t dev); +int ata_ahci_ch_suspend(device_t dev); +int ata_ahci_ch_resume(device_t dev); void ata_ahci_reset(device_t dev); int ata_marvell_edma_chipinit(device_t); int ata_sii_chipinit(device_t); diff --git a/sys/dev/ata/ata-sata.c b/sys/dev/ata/ata-sata.c index 642a94e..1151ca1 100644 --- a/sys/dev/ata/ata-sata.c +++ b/sys/dev/ata/ata-sata.c @@ -73,59 +73,141 @@ ata_sata_phy_check_events(device_t dev) } } +int +ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val) +{ + int r; + + if (port < 0) { + *val = ATA_IDX_INL(ch, reg); + return (0); + } else { + switch (reg) { + case ATA_SSTATUS: + r = 0; + break; + case ATA_SERROR: + r = 1; + break; + case ATA_SCONTROL: + r = 2; + break; + default: + return (EINVAL); + } + return (ch->hw.pm_read(ch->dev, port, r, val)); + } +} + +int +ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val) +{ + int r; + + if (port < 0) { + ATA_IDX_OUTL(ch, reg, val); + return (0); + } else { + switch (reg) { + case ATA_SERROR: + r = 1; + break; + case ATA_SCONTROL: + r = 2; + break; + default: + return (EINVAL); + } + return (ch->hw.pm_write(ch->dev, port, r, val)); + } +} + static int -ata_sata_connect(struct ata_channel *ch) +ata_sata_connect(struct ata_channel *ch, int port) { u_int32_t status; int timeout; /* wait up to 1 second for "connect well" */ for (timeout = 0; timeout < 100 ; timeout++) { - status = ATA_IDX_INL(ch, ATA_SSTATUS); + if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status)) + return (0); if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 || (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2) break; ata_udelay(10000); } if (timeout >= 100) { - if (bootverbose) - device_printf(ch->dev, "SATA connect status=%08x\n", status); + if (bootverbose) { + if (port < 0) { + device_printf(ch->dev, "SATA connect timeout status=%08x\n", + status); + } else { + device_printf(ch->dev, "p%d: SATA connect timeout status=%08x\n", + port, status); + } + } return 0; } - if (bootverbose) - device_printf(ch->dev, "SATA connect time=%dms\n", timeout * 10); + if (bootverbose) { + if (port < 0) { + device_printf(ch->dev, "SATA connect time=%dms status=%08x\n", + timeout * 10, status); + } else { + device_printf(ch->dev, "p%d: SATA connect time=%dms status=%08x\n", + port, timeout * 10, status); + } + } /* clear SATA error register */ - ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); + ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff); return 1; } int -ata_sata_phy_reset(device_t dev) +ata_sata_phy_reset(device_t dev, int port, int quick) { struct ata_channel *ch = device_get_softc(dev); int loop, retry; + uint32_t val; - if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE) - return ata_sata_connect(ch); + if (quick) { + if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val)) + return (0); + if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE) + return ata_sata_connect(ch, port); + } + if (bootverbose) { + if (port < 0) { + device_printf(dev, "hardware reset ...\n"); + } else { + device_printf(dev, "p%d: hardware reset ...\n", port); + } + } for (retry = 0; retry < 10; retry++) { for (loop = 0; loop < 10; loop++) { - ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET); + if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET)) + return (0); ata_udelay(100); - if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == - ATA_SC_DET_RESET) + if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val)) + return (0); + if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_RESET) break; } ata_udelay(5000); for (loop = 0; loop < 10; loop++) { - ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE | - ATA_SC_IPM_DIS_PARTIAL | - ATA_SC_IPM_DIS_SLUMBER); + if (ata_sata_scr_write(ch, port, ATA_SCONTROL, + ATA_SC_DET_IDLE | + ATA_SC_IPM_DIS_PARTIAL | + ATA_SC_IPM_DIS_SLUMBER)) + return (0); ata_udelay(100); - if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0) - return ata_sata_connect(ch); + if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val)) + return (0); + if ((val & ATA_SC_DET_MASK) == 0) + return ata_sata_connect(ch, port); } } return 0; @@ -237,14 +319,27 @@ ata_pm_identify(device_t dev) /* chip specific quirks */ switch (pm_chipid) { case 0x37261095: - /* Some of these bogusly reports 6 ports */ + /* This PM declares 6 ports, while only 5 of them are real. + * Port 5 is enclosure management bridge port, which has implementation + * problems, causing probe faults. Hide it for now. */ + device_printf(dev, "SiI 3726 (rev=%x) Port Multiplier with %d (5) ports\n", + pm_revision, pm_ports); pm_ports = 5; - device_printf(dev, "SiI 3726 r%x Portmultiplier with %d ports\n", + break; + + case 0x47261095: + /* This PM declares 7 ports, while only 5 of them are real. + * Port 5 is some fake "Config Disk" with 640 sectors size, + * port 6 is enclosure management bridge port. + * Both fake ports has implementation problems, causing + * probe faults. Hide them for now. */ + device_printf(dev, "SiI 4726 (rev=%x) Port Multiplier with %d (5) ports\n", pm_revision, pm_ports); + pm_ports = 5; break; default: - device_printf(dev, "Portmultiplier (id=%08x rev=%x) with %d ports\n", + device_printf(dev, "Port Multiplier (id=%08x rev=%x) with %d ports\n", pm_chipid, pm_revision, pm_ports); } @@ -253,41 +348,17 @@ ata_pm_identify(device_t dev) /* reset all ports and register if anything connected */ for (port=0; port < pm_ports; port++) { - u_int32_t signature, status; - int timeout; + u_int32_t signature; - if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_RESET)) { - device_printf(dev, "p%d: writing ATA_SC_DET_RESET failed\n", port); + if (!ata_sata_phy_reset(dev, port, 1)) continue; - } - - ata_udelay(5000); - - if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_IDLE)) { - device_printf(dev, "p%d: writing ATA_SC_DET_idle failed\n", port); - continue; - } - - ata_udelay(5000); - - /* wait up to 1 second for "connect well" */ - for (timeout = 0; timeout < 100 ; timeout++) { - ch->hw.pm_read(dev, port, 0, &status); - if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 || - (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2) - break; - ata_udelay(10000); - } - if (timeout >= 100) { - if (bootverbose) - device_printf(dev, "p%d: connect status=%08x\n", port, status); - continue; - } - if (bootverbose) - device_printf(dev, "p%d: connect time %dms\n", port, timeout * 10); - /* clear SERROR register */ - ch->hw.pm_write(dev, port, 1, 0xffffffff); + /* + * XXX: I have no idea how to properly wait for PMP port hardreset + * completion. Without this delay soft reset does not completes + * successfully. + */ + DELAY(1000000); signature = ch->hw.softreset(dev, port); diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c index 991d2ad..9e78132 100644 --- a/sys/dev/ata/chipsets/ata-ahci.c +++ b/sys/dev/ata/chipsets/ata-ahci.c @@ -59,10 +59,16 @@ static int ata_ahci_begin_transaction(struct ata_request *request); static int ata_ahci_end_transaction(struct ata_request *request); static int ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result); static int ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t result); +static int ata_ahci_hardreset(device_t dev, int port, uint32_t *signature); static u_int32_t ata_ahci_softreset(device_t dev, int port); static void ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); static int ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *equest); static void ata_ahci_dmainit(device_t dev); +static void ata_ahci_start(device_t dev); +static void ata_ahci_stop(device_t dev); +static void ata_ahci_clo(device_t dev); +static void ata_ahci_start_fr(device_t dev); +static void ata_ahci_stop_fr(device_t dev); /* * AHCI v1.x compliant SATA chipset support functions @@ -131,6 +137,8 @@ ata_ahci_chipinit(device_t dev) ctlr->reset = ata_ahci_reset; ctlr->ch_attach = ata_ahci_ch_attach; ctlr->ch_detach = ata_ahci_ch_detach; + ctlr->ch_suspend = ata_ahci_ch_suspend; + ctlr->ch_resume = ata_ahci_ch_resume; ctlr->setmode = ata_sata_setmode; ctlr->suspend = ata_ahci_suspend; ctlr->resume = ata_ahci_ctlr_reset; @@ -192,7 +200,6 @@ ata_ahci_suspend(device_t dev) return 0; } - int ata_ahci_ch_attach(device_t dev) { @@ -220,12 +227,22 @@ ata_ahci_ch_attach(device_t dev) ch->hw.pm_read = ata_ahci_pm_read; ch->hw.pm_write = ata_ahci_pm_write; + ata_ahci_ch_resume(dev); return 0; } int ata_ahci_ch_detach(device_t dev) { + + ata_ahci_ch_suspend(dev); + ata_dmafini(dev); + return (0); +} + +int +ata_ahci_ch_suspend(device_t dev) +{ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); int offset = ch->unit << 7; @@ -233,6 +250,8 @@ ata_ahci_ch_detach(device_t dev) /* Disable port interrupts. */ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); /* Reset command register. */ + ata_ahci_stop(dev); + ata_ahci_stop_fr(dev); ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 0); /* Allow everything including partial and slumber modes. */ @@ -243,7 +262,35 @@ ata_ahci_ch_detach(device_t dev) /* Disable PHY. */ ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_DISABLE); - ata_dmafini(dev); + return (0); +} + +int +ata_ahci_ch_resume(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + uint64_t work; + int offset = ch->unit << 7; + + /* Disable port interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); + + /* setup work areas */ + work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32); + + work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET; + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32); + + /* activate the channel and power/spin up device */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, + (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD)); + ata_ahci_start_fr(dev); + ata_ahci_start(dev); + return (0); } @@ -366,9 +413,6 @@ ata_ahci_begin_transaction(struct ata_request *request) ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ~ATA_AHCI_P_CMD_ATAPI); - /* set PM port to address */ - //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001); - /* issue command to controller */ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << request->tag)); @@ -465,9 +509,6 @@ ata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout) clp->bytecount = 0; clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET); - /* set PM port */ - //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001); - /* issue command to controller */ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1); @@ -480,7 +521,7 @@ ata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout) /* clear interrupts */ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, - ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); + ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset)); if (timeout && (count >= timeout)) { if (bootverbose) { @@ -559,7 +600,7 @@ ata_ahci_stop(device_t dev) /* kill off all activity on this channel */ cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST)); + cmd & ~ATA_AHCI_P_CMD_ST); /* XXX SOS this is not entirely wrong */ timeout = 0; @@ -617,10 +658,47 @@ ata_ahci_start(device_t dev) /* start operations on this channel */ cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST) | + cmd | ATA_AHCI_P_CMD_ST | (ch->devices & ATA_PORTMULTIPLIER ? ATA_AHCI_P_CMD_PMA : 0)); } +static void +ata_ahci_stop_fr(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + u_int32_t cmd; + int offset = ch->unit << 7; + int timeout; + + /* kill off all activity on this channel */ + cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd & ~ATA_AHCI_P_CMD_FRE); + + timeout = 0; + do { + DELAY(1000); + if (timeout++ > 1000) { + device_printf(dev, "stopping AHCI FR engine failed\n"); + break; + } + } + while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_FR); +} + +static void +ata_ahci_start_fr(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + u_int32_t cmd; + int offset = ch->unit << 7; + + /* start FIS reception on this channel */ + cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd | ATA_AHCI_P_CMD_FRE); +} + static int ata_ahci_wait_ready(device_t dev, int t) { @@ -628,13 +706,14 @@ ata_ahci_wait_ready(device_t dev, int t) struct ata_channel *ch = device_get_softc(dev); int offset = ch->unit << 7; int timeout = 0; + uint32_t val; - while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) & + while ((val = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset)) & (ATA_S_BUSY | ATA_S_DRQ)) { DELAY(1000); if (timeout++ > t) { - device_printf(dev, "port is not ready (timeout %dms)\n", t); - return (-1); + device_printf(dev, "port is not ready (timeout %dms) tfd = %08x\n", t, val); + return (EBUSY); } } if (bootverbose) @@ -642,6 +721,28 @@ ata_ahci_wait_ready(device_t dev, int t) return (0); } +static int +ata_ahci_hardreset(device_t dev, int port, uint32_t *signature) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + int offset = ch->unit << 7; + + *signature = 0xffffffff; + ata_ahci_stop(dev); + /* Reset port */ + if (!ata_sata_phy_reset(dev, port, 0)) + return (ENOENT); + /* Wait for clearing busy status. */ + if (ata_ahci_wait_ready(dev, 10000)) { + device_printf(dev, "hardware reset timeout\n"); + return (EBUSY); + } + *signature = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset); + ata_ahci_start(dev); + return (0); +} + static u_int32_t ata_ahci_softreset(device_t dev, int port) { @@ -679,9 +780,9 @@ ata_ahci_softreset(device_t dev, int port) ctp->cfis[1] = port & 0x0f; //ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM; ctp->cfis[15] = ATA_A_4BIT; - ata_ahci_issue_cmd(dev, 0, 1000); + ata_ahci_issue_cmd(dev, 0, 3000); - if (ata_ahci_wait_ready(dev, 1000)) { + if (ata_ahci_wait_ready(dev, 0)) { device_printf(dev, "software reset clear timeout\n"); return (-1); } @@ -694,7 +795,6 @@ ata_ahci_reset(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); - u_int64_t work; u_int32_t signature; int offset = ch->unit << 7; @@ -704,25 +804,7 @@ ata_ahci_reset(device_t dev) /* Disable port interrupts */ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0); - /* setup work areas */ - work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET; - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32); - - work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET; - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32); - - /* activate the channel and power/spin up device */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, - (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD)); - - ata_ahci_stop(dev); - - /* enable FIS based switching */ - //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, 0x00000003); - - if (!ata_sata_phy_reset(dev)) { + if (ata_ahci_hardreset(dev, -1, &signature)) { if (bootverbose) device_printf(dev, "AHCI reset done: phy reset found no device\n"); ch->devices = 0; @@ -733,8 +815,6 @@ ata_ahci_reset(device_t dev) return; } - ata_ahci_start(dev); - /* enable wanted port interrupts */ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | @@ -743,9 +823,6 @@ ata_ahci_reset(device_t dev) ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)); - /* Wait for initial TFD from device. */ - ata_ahci_wait_ready(dev, 10000); - /* only probe for PortMultiplier if HW has support */ if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) { signature = ata_ahci_softreset(dev, ATA_PM); diff --git a/sys/dev/ata/chipsets/ata-intel.c b/sys/dev/ata/chipsets/ata-intel.c index 8bd2f03..cae1778 100644 --- a/sys/dev/ata/chipsets/ata-intel.c +++ b/sys/dev/ata/chipsets/ata-intel.c @@ -517,7 +517,7 @@ ata_intel_31244_tf_write(struct ata_request *request) static void ata_intel_31244_reset(device_t dev) { - if (ata_sata_phy_reset(dev)) + if (ata_sata_phy_reset(dev, -1, 1)) ata_generic_reset(dev); } diff --git a/sys/dev/ata/chipsets/ata-jmicron.c b/sys/dev/ata/chipsets/ata-jmicron.c index 301b99b..b1e7aef 100644 --- a/sys/dev/ata/chipsets/ata-jmicron.c +++ b/sys/dev/ata/chipsets/ata-jmicron.c @@ -55,6 +55,8 @@ __FBSDID("$FreeBSD$"); static int ata_jmicron_chipinit(device_t dev); static int ata_jmicron_ch_attach(device_t dev); static int ata_jmicron_ch_detach(device_t dev); +static int ata_jmicron_ch_suspend(device_t dev); +static int ata_jmicron_ch_resume(device_t dev); static void ata_jmicron_reset(device_t dev); static void ata_jmicron_setmode(device_t dev, int mode); @@ -127,6 +129,8 @@ ata_jmicron_chipinit(device_t dev) ctlr->ch_attach = ata_jmicron_ch_attach; ctlr->ch_detach = ata_jmicron_ch_detach; + ctlr->ch_suspend = ata_jmicron_ch_suspend; + ctlr->ch_resume = ata_jmicron_ch_resume; ctlr->reset = ata_jmicron_reset; ctlr->setmode = ata_jmicron_setmode; @@ -173,6 +177,30 @@ ata_jmicron_ch_detach(device_t dev) return (error); } +static int +ata_jmicron_ch_suspend(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + int error = 0; + + if (ch->unit < ctlr->chip->cfg1) + error = ata_ahci_ch_suspend(dev); + return error; +} + +static int +ata_jmicron_ch_resume(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct ata_channel *ch = device_get_softc(dev); + int error = 0; + + if (ch->unit < ctlr->chip->cfg1) + error = ata_ahci_ch_resume(dev); + return (error); +} + static void ata_jmicron_reset(device_t dev) { diff --git a/sys/dev/ata/chipsets/ata-marvell.c b/sys/dev/ata/chipsets/ata-marvell.c index a0fa485..361bc5b 100644 --- a/sys/dev/ata/chipsets/ata-marvell.c +++ b/sys/dev/ata/chipsets/ata-marvell.c @@ -503,7 +503,7 @@ ata_marvell_edma_reset(device_t dev) ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0); /* enable channel and test for devices */ - if (ata_sata_phy_reset(dev)) + if (ata_sata_phy_reset(dev, -1, 1)) ata_generic_reset(dev); /* enable EDMA machinery */ diff --git a/sys/dev/ata/chipsets/ata-nvidia.c b/sys/dev/ata/chipsets/ata-nvidia.c index 7e03afa..9e1de81 100644 --- a/sys/dev/ata/chipsets/ata-nvidia.c +++ b/sys/dev/ata/chipsets/ata-nvidia.c @@ -249,7 +249,7 @@ ata_nvidia_status(device_t dev) static void ata_nvidia_reset(device_t dev) { - if (ata_sata_phy_reset(dev)) + if (ata_sata_phy_reset(dev, -1, 1)) ata_generic_reset(dev); } diff --git a/sys/dev/ata/chipsets/ata-promise.c b/sys/dev/ata/chipsets/ata-promise.c index 3856535..6b34596 100644 --- a/sys/dev/ata/chipsets/ata-promise.c +++ b/sys/dev/ata/chipsets/ata-promise.c @@ -769,7 +769,7 @@ ata_promise_mio_reset(device_t dev) if ((ctlr->chip->cfg2 == PR_SATA) || ((ctlr->chip->cfg2 == PR_CMBO) && (ch->unit < 2))) { - if (ata_sata_phy_reset(dev)) + if (ata_sata_phy_reset(dev, -1, 1)) ata_generic_reset(dev); /* reset and enable plug/unplug intr */ @@ -805,7 +805,7 @@ ata_promise_mio_reset(device_t dev) (ATA_INL(ctlr->r_res2, 0x414 + (ch->unit << 8)) & ~0x00000003) | 0x00000001); - if (ata_sata_phy_reset(dev)) { + if (ata_sata_phy_reset(dev, -1, 1)) { u_int32_t signature = ch->hw.softreset(dev, ATA_PM); if (1 | bootverbose) diff --git a/sys/dev/ata/chipsets/ata-siliconimage.c b/sys/dev/ata/chipsets/ata-siliconimage.c index f5093c7..b163276 100644 --- a/sys/dev/ata/chipsets/ata-siliconimage.c +++ b/sys/dev/ata/chipsets/ata-siliconimage.c @@ -380,7 +380,7 @@ ata_sii_status(device_t dev) static void ata_sii_reset(device_t dev) { - if (ata_sata_phy_reset(dev)) + if (ata_sata_phy_reset(dev, -1, 1)) ata_generic_reset(dev); } @@ -832,7 +832,7 @@ ata_siiprb_reset(device_t dev) } /* reset phy */ - if (!ata_sata_phy_reset(dev)) { + if (!ata_sata_phy_reset(dev, -1, 1)) { if (bootverbose) device_printf(dev, "phy reset found no device\n"); ch->devices = 0; diff --git a/sys/dev/ata/chipsets/ata-sis.c b/sys/dev/ata/chipsets/ata-sis.c index 1d9dac7..8e02ee9 100644 --- a/sys/dev/ata/chipsets/ata-sis.c +++ b/sys/dev/ata/chipsets/ata-sis.c @@ -226,7 +226,7 @@ ata_sis_ch_attach(device_t dev) static void ata_sis_reset(device_t dev) { - if (ata_sata_phy_reset(dev)) + if (ata_sata_phy_reset(dev, -1, 1)) ata_generic_reset(dev); } diff --git a/sys/dev/ata/chipsets/ata-via.c b/sys/dev/ata/chipsets/ata-via.c index 4530adf..525ca2f 100644 --- a/sys/dev/ata/chipsets/ata-via.c +++ b/sys/dev/ata/chipsets/ata-via.c @@ -269,7 +269,7 @@ ata_via_reset(device_t dev) if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1)) ata_generic_reset(dev); else - if (ata_sata_phy_reset(dev)) + if (ata_sata_phy_reset(dev, -1, 1)) ata_generic_reset(dev); } |