Date: Tue, 31 Mar 2009 09:19:56 +0200 From: Roman Divacky <rdivacky@FreeBSD.org> To: Alexander Motin <mav@FreeBSD.org> Cc: svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org Subject: Re: svn commit: r190581 - in head/sys: . amd64/include/xen arm/arm cddl/dev/dtnfsclient contrib/pf dev/ata dev/ata/chipsets dev/cxgb dev/sound/usb dev/usb dev/usb/bluetooth dev/usb/controller dev/usb/i... Message-ID: <20090331071956.GA6799@freebsd.org> In-Reply-To: <200903302218.n2UMIc6t080193@svn.freebsd.org> References: <200903302218.n2UMIc6t080193@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
are you sure about the merge info? On Mon, Mar 30, 2009 at 10:18:38PM +0000, Alexander Motin wrote: > Author: mav > Date: Mon Mar 30 22:18:38 2009 > New Revision: 190581 > URL: http://svn.freebsd.org/changeset/base/190581 > > Log: > Integrate user/mav/ata branch: > > Add ch_suspend/ch_resume methods for PCI controllers and implement them > for AHCI. Refactor AHCI channel initialization according to it. > > Fix Port Multipliers operation. It is far from perfect yet, but works now. > Tested with JMicron JMB363 AHCI + SiI 3726 PMP pair. > Previous version was also tested with SiI 4726 PMP. > > Hardware sponsored by: Vitsch Electronics / VEHosting.nl > > Modified: > head/sys/ (props changed) > head/sys/amd64/include/xen/ (props changed) > head/sys/arm/arm/cpufunc_asm_sheeva.S (props changed) > head/sys/cddl/dev/dtnfsclient/ (props changed) > head/sys/contrib/pf/ (props changed) > head/sys/dev/ata/ata-pci.c > head/sys/dev/ata/ata-pci.h > head/sys/dev/ata/ata-sata.c > head/sys/dev/ata/ata-usb.c (props changed) > head/sys/dev/ata/chipsets/ata-ahci.c > head/sys/dev/ata/chipsets/ata-intel.c > head/sys/dev/ata/chipsets/ata-jmicron.c > head/sys/dev/ata/chipsets/ata-marvell.c > head/sys/dev/ata/chipsets/ata-nvidia.c > head/sys/dev/ata/chipsets/ata-promise.c > head/sys/dev/ata/chipsets/ata-siliconimage.c > head/sys/dev/ata/chipsets/ata-sis.c > head/sys/dev/ata/chipsets/ata-via.c > head/sys/dev/cxgb/ (props changed) > head/sys/dev/sound/usb/uaudio.c (props changed) > head/sys/dev/sound/usb/uaudio.h (props changed) > head/sys/dev/sound/usb/uaudio_pcm.c (props changed) > head/sys/dev/sound/usb/uaudioreg.h (props changed) > head/sys/dev/usb/README.TXT (props changed) > head/sys/dev/usb/bluetooth/TODO.TXT (props changed) > head/sys/dev/usb/bluetooth/ng_ubt.c (props changed) > head/sys/dev/usb/bluetooth/ng_ubt_var.h (props changed) > head/sys/dev/usb/bluetooth/ubtbcmfw.c (props changed) > head/sys/dev/usb/controller/at91dci.c (props changed) > head/sys/dev/usb/controller/at91dci.h (props changed) > head/sys/dev/usb/controller/at91dci_atmelarm.c (props changed) > head/sys/dev/usb/controller/atmegadci.c (props changed) > head/sys/dev/usb/controller/atmegadci.h (props changed) > head/sys/dev/usb/controller/atmegadci_atmelarm.c (props changed) > head/sys/dev/usb/controller/ehci.c (props changed) > head/sys/dev/usb/controller/ehci.h (props changed) > head/sys/dev/usb/controller/ehci_ixp4xx.c (props changed) > head/sys/dev/usb/controller/ehci_mbus.c (props changed) > head/sys/dev/usb/controller/ehci_pci.c (props changed) > head/sys/dev/usb/controller/musb_otg.c (props changed) > head/sys/dev/usb/controller/musb_otg.h (props changed) > head/sys/dev/usb/controller/musb_otg_atmelarm.c (props changed) > head/sys/dev/usb/controller/ohci.c (props changed) > head/sys/dev/usb/controller/ohci.h (props changed) > head/sys/dev/usb/controller/ohci_atmelarm.c (props changed) > head/sys/dev/usb/controller/ohci_pci.c (props changed) > head/sys/dev/usb/controller/uhci.c (props changed) > head/sys/dev/usb/controller/uhci.h (props changed) > head/sys/dev/usb/controller/uhci_pci.c (props changed) > head/sys/dev/usb/controller/usb_controller.c (props changed) > head/sys/dev/usb/controller/uss820dci.c (props changed) > head/sys/dev/usb/controller/uss820dci.h (props changed) > head/sys/dev/usb/controller/uss820dci_atmelarm.c (props changed) > head/sys/dev/usb/input/uhid.c (props changed) > head/sys/dev/usb/input/ukbd.c (props changed) > head/sys/dev/usb/input/ums.c (props changed) > head/sys/dev/usb/input/usb_rdesc.h (props changed) > head/sys/dev/usb/misc/udbp.c (props changed) > head/sys/dev/usb/misc/udbp.h (props changed) > head/sys/dev/usb/misc/ufm.c (props changed) > head/sys/dev/usb/net/if_aue.c (props changed) > head/sys/dev/usb/net/if_auereg.h (props changed) > head/sys/dev/usb/net/if_axe.c (props changed) > head/sys/dev/usb/net/if_axereg.h (props changed) > head/sys/dev/usb/net/if_cdce.c (props changed) > head/sys/dev/usb/net/if_cdcereg.h (props changed) > head/sys/dev/usb/net/if_cue.c (props changed) > head/sys/dev/usb/net/if_cuereg.h (props changed) > head/sys/dev/usb/net/if_kue.c (props changed) > head/sys/dev/usb/net/if_kuefw.h (props changed) > head/sys/dev/usb/net/if_kuereg.h (props changed) > head/sys/dev/usb/net/if_rue.c (props changed) > head/sys/dev/usb/net/if_ruereg.h (props changed) > head/sys/dev/usb/net/if_udav.c (props changed) > head/sys/dev/usb/net/if_udavreg.h (props changed) > head/sys/dev/usb/net/usb_ethernet.c (props changed) > head/sys/dev/usb/net/usb_ethernet.h (props changed) > head/sys/dev/usb/quirk/usb_quirk.c (props changed) > head/sys/dev/usb/quirk/usb_quirk.h (props changed) > head/sys/dev/usb/serial/u3g.c (props changed) > head/sys/dev/usb/serial/uark.c (props changed) > head/sys/dev/usb/serial/ubsa.c (props changed) > head/sys/dev/usb/serial/ubser.c (props changed) > head/sys/dev/usb/serial/uchcom.c (props changed) > head/sys/dev/usb/serial/ucycom.c (props changed) > head/sys/dev/usb/serial/ufoma.c (props changed) > head/sys/dev/usb/serial/uftdi.c (props changed) > head/sys/dev/usb/serial/uftdi_reg.h (props changed) > head/sys/dev/usb/serial/ugensa.c (props changed) > head/sys/dev/usb/serial/uipaq.c (props changed) > head/sys/dev/usb/serial/ulpt.c (props changed) > head/sys/dev/usb/serial/umct.c (props changed) > head/sys/dev/usb/serial/umodem.c (props changed) > head/sys/dev/usb/serial/umoscom.c (props changed) > head/sys/dev/usb/serial/uplcom.c (props changed) > head/sys/dev/usb/serial/usb_serial.c (props changed) > head/sys/dev/usb/serial/usb_serial.h (props changed) > head/sys/dev/usb/serial/uslcom.c (props changed) > head/sys/dev/usb/serial/uvisor.c (props changed) > head/sys/dev/usb/serial/uvscom.c (props changed) > head/sys/dev/usb/storage/rio500_usb.h (props changed) > head/sys/dev/usb/storage/umass.c (props changed) > head/sys/dev/usb/storage/urio.c (props changed) > head/sys/dev/usb/storage/ustorage_fs.c (props changed) > head/sys/dev/usb/template/usb_template.c (props changed) > head/sys/dev/usb/template/usb_template.h (props changed) > head/sys/dev/usb/template/usb_template_cdce.c (props changed) > head/sys/dev/usb/template/usb_template_msc.c (props changed) > head/sys/dev/usb/template/usb_template_mtp.c (props changed) > head/sys/dev/usb/ufm_ioctl.h (props changed) > head/sys/dev/usb/usb.h (props changed) > head/sys/dev/usb/usb_bus.h (props changed) > head/sys/dev/usb/usb_busdma.c (props changed) > head/sys/dev/usb/usb_busdma.h (props changed) > head/sys/dev/usb/usb_cdc.h (props changed) > head/sys/dev/usb/usb_compat_linux.c (props changed) > head/sys/dev/usb/usb_compat_linux.h (props changed) > head/sys/dev/usb/usb_controller.h (props changed) > head/sys/dev/usb/usb_core.c (props changed) > head/sys/dev/usb/usb_core.h (props changed) > head/sys/dev/usb/usb_debug.c (props changed) > head/sys/dev/usb/usb_debug.h (props changed) > head/sys/dev/usb/usb_defs.h (props changed) > head/sys/dev/usb/usb_dev.c (props changed) > head/sys/dev/usb/usb_dev.h (props changed) > head/sys/dev/usb/usb_device.c (props changed) > head/sys/dev/usb/usb_device.h (props changed) > head/sys/dev/usb/usb_dynamic.c (props changed) > head/sys/dev/usb/usb_dynamic.h (props changed) > head/sys/dev/usb/usb_endian.h (props changed) > head/sys/dev/usb/usb_error.c (props changed) > head/sys/dev/usb/usb_error.h (props changed) > head/sys/dev/usb/usb_generic.c (props changed) > head/sys/dev/usb/usb_generic.h (props changed) > head/sys/dev/usb/usb_handle_request.c (props changed) > head/sys/dev/usb/usb_handle_request.h (props changed) > head/sys/dev/usb/usb_hid.c (props changed) > head/sys/dev/usb/usb_hid.h (props changed) > head/sys/dev/usb/usb_hub.c (props changed) > head/sys/dev/usb/usb_hub.h (props changed) > head/sys/dev/usb/usb_if.m (props changed) > head/sys/dev/usb/usb_ioctl.h (props changed) > head/sys/dev/usb/usb_lookup.c (props changed) > head/sys/dev/usb/usb_lookup.h (props changed) > head/sys/dev/usb/usb_mbuf.c (props changed) > head/sys/dev/usb/usb_mbuf.h (props changed) > head/sys/dev/usb/usb_mfunc.h (props changed) > head/sys/dev/usb/usb_msctest.c (props changed) > head/sys/dev/usb/usb_msctest.h (props changed) > head/sys/dev/usb/usb_parse.c (props changed) > head/sys/dev/usb/usb_parse.h (props changed) > head/sys/dev/usb/usb_pci.h (props changed) > head/sys/dev/usb/usb_process.c (props changed) > head/sys/dev/usb/usb_process.h (props changed) > head/sys/dev/usb/usb_request.c (props changed) > head/sys/dev/usb/usb_request.h (props changed) > head/sys/dev/usb/usb_revision.h (props changed) > head/sys/dev/usb/usb_sw_transfer.c (props changed) > head/sys/dev/usb/usb_sw_transfer.h (props changed) > head/sys/dev/usb/usb_transfer.c (props changed) > head/sys/dev/usb/usb_transfer.h (props changed) > head/sys/dev/usb/usb_util.c (props changed) > head/sys/dev/usb/usb_util.h (props changed) > head/sys/dev/usb/usbdevs (props changed) > head/sys/dev/usb/usbhid.h (props changed) > head/sys/dev/usb/wlan/if_rum.c (props changed) > head/sys/dev/usb/wlan/if_rumfw.h (props changed) > head/sys/dev/usb/wlan/if_rumreg.h (props changed) > head/sys/dev/usb/wlan/if_rumvar.h (props changed) > head/sys/dev/usb/wlan/if_ural.c (props changed) > head/sys/dev/usb/wlan/if_uralreg.h (props changed) > head/sys/dev/usb/wlan/if_uralvar.h (props changed) > head/sys/dev/usb/wlan/if_zyd.c (props changed) > head/sys/dev/usb/wlan/if_zydfw.h (props changed) > head/sys/dev/usb/wlan/if_zydreg.h (props changed) > head/sys/dev/usb/wlan/usb_wlan.h (props changed) > head/sys/dev/xen/netfront/ (props changed) > head/sys/dev/xen/xenpci/ (props changed) > head/sys/legacy/dev/ata/ata-usb.c (props changed) > head/sys/legacy/dev/sound/usb/uaudio.c (props changed) > head/sys/legacy/dev/sound/usb/uaudio.h (props changed) > head/sys/legacy/dev/sound/usb/uaudio_pcm.c (props changed) > head/sys/legacy/dev/sound/usb/uaudioreg.h (props changed) > head/sys/legacy/dev/usb/ (props changed) > head/sys/legacy/dev/usb/ehci_ixp4xx.c (props changed) > head/sys/mips/mips/elf64_machdep.c (props changed) > head/sys/modules/dtrace/dtnfsclient/ (props changed) > head/sys/modules/ip6_mroute_mod/ (props changed) > head/sys/modules/ipmi/ipmi_linux/ (props changed) > head/sys/xen/evtchn.h (props changed) > head/sys/xen/hypervisor.h (props changed) > head/sys/xen/xen_intr.h (props changed) > > Modified: head/sys/dev/ata/ata-pci.c > ============================================================================== > --- head/sys/dev/ata/ata-pci.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/ata-pci.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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); > } > > > Modified: head/sys/dev/ata/ata-pci.h > ============================================================================== > --- head/sys/dev/ata/ata-pci.h Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/ata-pci.h Mon Mar 30 22:18:38 2009 (r190581) > @@ -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); > > Modified: head/sys/dev/ata/ata-sata.c > ============================================================================== > --- head/sys/dev/ata/ata-sata.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/ata-sata.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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); > > > Modified: head/sys/dev/ata/chipsets/ata-ahci.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-ahci.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-ahci.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -59,10 +59,16 @@ static int ata_ahci_begin_transaction(st > 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_re > 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 > 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 > > /* 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 por > 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); > > Modified: head/sys/dev/ata/chipsets/ata-intel.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-intel.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-intel.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -517,7 +517,7 @@ ata_intel_31244_tf_write(struct ata_requ > 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); > } > > > Modified: head/sys/dev/ata/chipsets/ata-jmicron.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-jmicron.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-jmicron.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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) > { > > Modified: head/sys/dev/ata/chipsets/ata-marvell.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-marvell.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-marvell.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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 */ > > Modified: head/sys/dev/ata/chipsets/ata-nvidia.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-nvidia.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-nvidia.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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); > } > > > Modified: head/sys/dev/ata/chipsets/ata-promise.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-promise.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-promise.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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) > > Modified: head/sys/dev/ata/chipsets/ata-siliconimage.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-siliconimage.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-siliconimage.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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; > > Modified: head/sys/dev/ata/chipsets/ata-sis.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-sis.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-sis.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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); > } > > > Modified: head/sys/dev/ata/chipsets/ata-via.c > ============================================================================== > --- head/sys/dev/ata/chipsets/ata-via.c Mon Mar 30 21:54:39 2009 (r190580) > +++ head/sys/dev/ata/chipsets/ata-via.c Mon Mar 30 22:18:38 2009 (r190581) > @@ -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); > } >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090331071956.GA6799>