diff options
author | Seth Goldberg <Seth.Goldberg@Sun.COM> | 2009-01-14 18:06:11 -0800 |
---|---|---|
committer | Seth Goldberg <Seth.Goldberg@Sun.COM> | 2009-01-14 18:06:11 -0800 |
commit | 0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2 (patch) | |
tree | c7a7d51bda6f52339f7b34722a18ffba20493795 | |
parent | c513743f1851cb6b7265d554537508ded93c4c71 (diff) | |
download | illumos-joyent-0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2.tar.gz |
6759202 ata: S3 suspend to ram hangs in pci_save_config_regs()
6759210 uhci: suspend to ram on Toshiba Tecra S1 hangs in uhci_cpr_suspend()
6759217 uppc: state of legacy pic must be saved / restored to support suspend to ram
6761267 pci interrupt routing entries not restored after wakeup from S3 sleep
6759220 ipw2100: needs DDI_SUSPEND / DDI_RESUME support, for suspend to ram
6761274 acpi-crs property not freed after wakeup from s3 suspend to ram
6766845 Tecra S1: ata0 "timeout: abort request" errors for PATA HDD after S3 resume
Contributed by Juergen Keil <jk@tools.de>.
-rw-r--r-- | usr/src/uts/common/io/ipw/ipw2100.c | 137 | ||||
-rw-r--r-- | usr/src/uts/common/io/ipw/ipw2100_impl.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/io/pci-ide/pci-ide.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/io/usb/hcd/uhci/uhci.c | 39 | ||||
-rw-r--r-- | usr/src/uts/common/sys/usb/hcd/uhci/uhci.h | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/psm/uppc.c | 142 | ||||
-rw-r--r-- | usr/src/uts/intel/io/acpica/acpica.c | 4 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/controller/ata/ata_common.c | 39 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/controller/ata/ata_common.h | 3 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/controller/ata/atapi.c | 27 |
10 files changed, 352 insertions, 55 deletions
diff --git a/usr/src/uts/common/io/ipw/ipw2100.c b/usr/src/uts/common/io/ipw/ipw2100.c index a5feab7846..e882cae4b1 100644 --- a/usr/src/uts/common/io/ipw/ipw2100.c +++ b/usr/src/uts/common/io/ipw/ipw2100.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -172,6 +172,12 @@ static int ipw_wificfg_disassoc(struct ipw2100_softc *sc, wldp_t *outfp); /* + * Suspend / Resume operations + */ +static int ipw2100_cpr_suspend(struct ipw2100_softc *sc); +static int ipw2100_cpr_resume(struct ipw2100_softc *sc); + +/* * Mac Call Back entries */ mac_callbacks_t ipw2100_m_callbacks = { @@ -254,7 +260,17 @@ ipw2100_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) wifi_data_t wd = { 0 }; mac_register_t *macp; - if (cmd != DDI_ATTACH) { + switch (cmd) { + case DDI_ATTACH: + break; + case DDI_RESUME: + sc = ddi_get_soft_state(ipw2100_ssp, ddi_get_instance(dip)); + if (sc == NULL) { + err = DDI_FAILURE; + goto fail1; + } + return (ipw2100_cpr_resume(sc)); + default: err = DDI_FAILURE; goto fail1; } @@ -508,8 +524,14 @@ ipw2100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) ASSERT(sc != NULL); - if (cmd != DDI_DETACH) + switch (cmd) { + case DDI_DETACH: + break; + case DDI_SUSPEND: + return (ipw2100_cpr_suspend(sc)); + default: return (DDI_FAILURE); + } /* * Destroy the mf_thread @@ -523,7 +545,7 @@ ipw2100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) mutex_exit(&sc->sc_mflock); /* - * Unregiste from the MAC layer subsystem + * Unregister from the MAC layer subsystem */ err = mac_unregister(sc->sc_ic.ic_mach); if (err != DDI_SUCCESS) @@ -558,6 +580,103 @@ ipw2100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) return (DDI_SUCCESS); } +int +ipw2100_cpr_suspend(struct ipw2100_softc *sc) +{ + IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT, + "ipw2100_cpr_suspend(): enter\n")); + + /* + * Destroy the mf_thread + */ + mutex_enter(&sc->sc_mflock); + sc->sc_mfthread_switch = 0; + while (sc->sc_mf_thread != NULL) { + if (cv_wait_sig(&sc->sc_mfthread_cv, &sc->sc_mflock) == 0) + break; + } + mutex_exit(&sc->sc_mflock); + + /* + * stop the hardware; this mask all interrupts + */ + ipw2100_stop(sc); + sc->sc_flags &= ~IPW2100_FLAG_RUNNING; + sc->sc_suspended = 1; + + (void) ipw2100_free_firmware(sc); + ipw2100_ring_free(sc); + + return (DDI_SUCCESS); +} + +int +ipw2100_cpr_resume(struct ipw2100_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + dev_info_t *dip = sc->sc_dip; + int err; + + IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT, + "ipw2100_cpr_resume(): enter\n")); + + /* + * Reset the chip + */ + err = ipw2100_chip_reset(sc); + if (err != DDI_SUCCESS) { + IPW2100_WARN((dip, CE_WARN, + "ipw2100_attach(): reset failed\n")); + return (DDI_FAILURE); + } + + /* + * Get the hw conf, including MAC address, then init all rings. + */ + /* ipw2100_hwconf_get(sc); */ + err = ipw2100_ring_init(sc); + if (err != DDI_SUCCESS) { + IPW2100_WARN((dip, CE_WARN, + "ipw2100_attach(): " + "unable to allocate and initialize rings\n")); + return (DDI_FAILURE); + } + + /* + * Cache firmware, always return true + */ + (void) ipw2100_cache_firmware(sc); + + /* + * Notify link is down now + */ + mac_link_update(ic->ic_mach, LINK_STATE_DOWN); + + /* + * create the mf thread to handle the link status, + * recovery fatal error, etc. + */ + sc->sc_mfthread_switch = 1; + if (sc->sc_mf_thread == NULL) + sc->sc_mf_thread = thread_create((caddr_t)NULL, 0, + ipw2100_thread, sc, 0, &p0, TS_RUN, minclsyspri); + + /* + * enable all interrupts + */ + sc->sc_suspended = 0; + ipw2100_csr_put32(sc, IPW2100_CSR_INTR_MASK, IPW2100_INTR_MASK_ALL); + + /* + * initialize ipw2100 hardware + */ + (void) ipw2100_init(sc); + + sc->sc_flags |= IPW2100_FLAG_RUNNING; + + return (DDI_SUCCESS); +} + /* * quiesce(9E) entry point. * This function is called when the system is single-threaded at high @@ -977,6 +1096,9 @@ ipw2100_init(struct ipw2100_softc *sc) { int err; + IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT, + "ipw2100_init(): enter\n")); + /* * no firmware is available, return fail directly */ @@ -998,6 +1120,8 @@ ipw2100_init(struct ipw2100_softc *sc) /* * load microcode */ + IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT, + "ipw2100_init(): loading microcode\n")); err = ipw2100_load_uc(sc); if (err != DDI_SUCCESS) { IPW2100_WARN((sc->sc_dip, CE_WARN, @@ -1012,6 +1136,8 @@ ipw2100_init(struct ipw2100_softc *sc) /* * load firmware */ + IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT, + "ipw2100_init(): loading firmware\n")); err = ipw2100_load_fw(sc); if (err != DDI_SUCCESS) { IPW2100_WARN((sc->sc_dip, CE_WARN, @@ -2537,6 +2663,9 @@ ipw2100_intr(caddr_t arg) struct ipw2100_bd *rxbd; #endif + if (sc->sc_suspended) + return (DDI_INTR_UNCLAIMED); + ireg = ipw2100_csr_get32(sc, IPW2100_CSR_INTR); if (!(ireg & IPW2100_INTR_MASK_ALL)) diff --git a/usr/src/uts/common/io/ipw/ipw2100_impl.h b/usr/src/uts/common/io/ipw/ipw2100_impl.h index f0de7961d5..7207468323 100644 --- a/usr/src/uts/common/io/ipw/ipw2100_impl.h +++ b/usr/src/uts/common/io/ipw/ipw2100_impl.h @@ -1,5 +1,5 @@ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -99,6 +99,7 @@ struct ipw2100_softc { int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); int sc_authmode; + int sc_suspended; /* CSR */ ddi_acc_handle_t sc_ioh; caddr_t sc_regs; diff --git a/usr/src/uts/common/io/pci-ide/pci-ide.c b/usr/src/uts/common/io/pci-ide/pci-ide.c index 7156aaa091..87f228c170 100644 --- a/usr/src/uts/common/io/pci-ide/pci-ide.c +++ b/usr/src/uts/common/io/pci-ide/pci-ide.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -381,6 +381,13 @@ pciide_ddi_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop, return (rc); + case DDI_CTLOPS_ATTACH: + case DDI_CTLOPS_DETACH: + /* + * Don't pass child ide ATTACH/DETACH to parent + */ + return (DDI_SUCCESS); + default: return (ddi_ctlops(dip, rdip, ctlop, arg, result)); } diff --git a/usr/src/uts/common/io/usb/hcd/uhci/uhci.c b/usr/src/uts/common/io/usb/hcd/uhci/uhci.c index 4da8376838..0dfca00755 100644 --- a/usr/src/uts/common/io/usb/hcd/uhci/uhci.c +++ b/usr/src/uts/common/io/usb/hcd/uhci/uhci.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -850,6 +850,9 @@ uhci_cleanup(uhci_state_t *uhcip) static int uhci_cpr_suspend(uhci_state_t *uhcip) { + uint16_t cmd_reg; + int i; + USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_cpr_suspend:"); @@ -861,20 +864,36 @@ uhci_cpr_suspend(uhci_state_t *uhcip) mutex_enter(&uhcip->uhci_int_mutex); - /* Disable interrupts */ - Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); + /* Stop the Host Controller */ + cmd_reg = Get_OpReg16(USBCMD); + cmd_reg &= ~USBCMD_REG_HC_RUN; + Set_OpReg16(USBCMD, cmd_reg); - mutex_exit(&uhcip->uhci_int_mutex); + /* + * Wait for the duration of an SOF period until the host controller + * reaches the stopped state, indicated by the HCHalted bit in the + * USB status register. + */ + for (i = 0; i <= UHCI_TIMEWAIT / 1000; i++) { + if (Get_OpReg16(USBSTS) & USBSTS_REG_HC_HALTED) + break; + drv_usecwait(1000); + } - /* Wait for SOF time to handle the scheduled interrupt */ - delay(drv_usectohz(UHCI_TIMEWAIT)); + USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, + "uhci_cpr_suspend: waited %d milliseconds for hc to halt", i); - mutex_enter(&uhcip->uhci_int_mutex); - /* Stop the Host Controller */ - Set_OpReg16(USBCMD, 0); + /* Disable interrupts */ + Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); + + /* Clear any scheduled pending interrupts */ + Set_OpReg16(USBSTS, USBSTS_REG_HC_HALTED | + USBSTS_REG_HC_PROCESS_ERR | USBSTS_REG_HOST_SYS_ERR | + USBSTS_REG_RESUME_DETECT | USBSTS_REG_USB_ERR_INTR | + USBSTS_REG_USB_INTR); /* Set Global Suspend bit */ - Set_OpReg16(USBCMD, USBCMD_REG_ENER_GBL_SUSPEND); + Set_OpReg16(USBCMD, USBCMD_REG_ENTER_GBL_SUSPEND); /* Set host controller soft state to suspend */ uhcip->uhci_hc_soft_state = UHCI_CTLR_SUSPEND_STATE; diff --git a/usr/src/uts/common/sys/usb/hcd/uhci/uhci.h b/usr/src/uts/common/sys/usb/hcd/uhci/uhci.h index 0b547ff4e9..a275e13bfe 100644 --- a/usr/src/uts/common/sys/usb/hcd/uhci/uhci.h +++ b/usr/src/uts/common/sys/usb/hcd/uhci/uhci.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -68,7 +68,7 @@ typedef volatile struct hcr_regs { #define USBCMD_REG_CONFIG_FLAG 0x0040 #define USBCMD_REG_SW_DEBUG 0x0020 #define USBCMD_REG_FGBL_RESUME 0x0010 -#define USBCMD_REG_ENER_GBL_SUSPEND 0x0008 +#define USBCMD_REG_ENTER_GBL_SUSPEND 0x0008 #define USBCMD_REG_GBL_RESET 0x0004 #define USBCMD_REG_HC_RESET 0x0002 #define USBCMD_REG_HC_RUN 0x0001 diff --git a/usr/src/uts/i86pc/io/psm/uppc.c b/usr/src/uts/i86pc/io/psm/uppc.c index 2fd3f860c5..0b6faee267 100644 --- a/usr/src/uts/i86pc/io/psm/uppc.c +++ b/usr/src/uts/i86pc/io/psm/uppc.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #define PSMI_1_6 #include <sys/mutex.h> @@ -36,6 +34,7 @@ #include <sys/promif.h> #include <sys/psm.h> #include <sys/pit.h> +#include <sys/apic.h> #include <sys/psm_common.h> #include <sys/atomic.h> #include <sys/archsystm.h> @@ -47,6 +46,7 @@ */ static void uppc_softinit(void); static void uppc_picinit(); +static int uppc_post_cpu_start(void); static int uppc_clkinit(int); static int uppc_addspl(int irqno, int ipl, int min_ipl, int max_ipl); static int uppc_delspl(int irqno, int ipl, int min_ipl, int max_ipl); @@ -56,6 +56,7 @@ static int uppc_probe(void); static int uppc_translate_irq(dev_info_t *dip, int irqno); static void uppc_shutdown(int cmd, int fcn); static void uppc_preshutdown(int cmd, int fcn); +static int uppc_state(psm_state_request_t *request); static int uppc_init_acpi(void); static void uppc_setspl(int); static int uppc_intr_enter(int, int *); @@ -154,7 +155,7 @@ static struct psm_ops uppc_ops = { uppc_get_next_processorid, /* psm_get_next_processorid */ (int (*)(processorid_t, caddr_t))NULL, /* psm_cpu_start */ - (int (*)(void))NULL, /* psm_post_cpu_start */ + uppc_post_cpu_start, /* psm_post_cpu_start */ uppc_shutdown, /* psm_shutdown */ (int (*)(int, int))NULL, /* psm_get_ipivect */ (void (*)(processorid_t, int))NULL, /* psm_send_ipi */ @@ -170,12 +171,14 @@ static struct psm_ops uppc_ops = { uppc_preshutdown, /* psm_preshutdown */ (int (*)(dev_info_t *, ddi_intr_handle_impl_t *, - psm_intr_op_t, int *))NULL /* psm_intr_ops */ + psm_intr_op_t, int *))NULL, /* psm_intr_ops */ + + uppc_state /* psm_state */ }; static struct psm_info uppc_info = { - PSM_INFO_VER01_5, /* version */ + PSM_INFO_VER01_6, /* version */ PSM_OWN_SYS_DEFAULT, /* ownership */ (struct psm_ops *)&uppc_ops, /* operation */ "uppc", /* machine name */ @@ -282,6 +285,27 @@ uppc_picinit() (void) uppc_addspl(uppc_sci, SCI_IPL, SCI_IPL, SCI_IPL); } +static int +uppc_post_cpu_start(void) +{ + /* + * On uppc machines psm_post_cpu_start is called during S3 resume + * on the boot cpu from assembly, using the ap_mlsetup vector. + */ + + /* + * Init master and slave pic + */ + picsetup(); + + /* + * program timer 0 + */ + (void) uppc_clkinit(hz); + + return (PSM_SUCCESS); +} + /*ARGSUSED3*/ static int uppc_addspl(int irqno, int ipl, int min_ipl, int max_ipl) @@ -486,6 +510,112 @@ uppc_shutdown(int cmd, int fcn) (void) acpi_poweroff(); } + +static int +uppc_acpi_enter_picmode(void) +{ + ACPI_OBJECT_LIST arglist; + ACPI_OBJECT arg; + ACPI_STATUS status; + + /* Setup parameter object */ + arglist.Count = 1; + arglist.Pointer = &arg; + arg.Type = ACPI_TYPE_INTEGER; + arg.Integer.Value = ACPI_PIC_MODE; + + status = AcpiEvaluateObject(NULL, "\\_PIC", &arglist, NULL); + if (ACPI_FAILURE(status)) + return (PSM_FAILURE); + else + return (PSM_SUCCESS); +} + + +struct pic_state { + int8_t mmask; + int8_t smask; + uint16_t elcr; +}; + + +static void +pic_save_state(struct pic_state *sp) +{ + struct standard_pic *pp; + int vecno; + + /* + * Only the PIC masks and the ELCR can be saved; + * other 8259 state is write-only + */ + + /* + * save current master and slave interrupt mask + */ + pp = &pics0; + sp->smask = pp->c_curmask[0]; + sp->mmask = pp->c_curmask[1]; + + /* + * save edge/level configuration for isa interrupts + */ + sp->elcr = 0; + for (vecno = 0; vecno <= MAX_ISA_IRQ; vecno++) + sp->elcr |= psm_get_elcr(vecno) << vecno; +} + +static void +pic_restore_state(struct pic_state *sp) +{ + int vecno; + + /* Restore master and slave interrupt masks */ + outb(SIMR_PORT, sp->smask); + outb(MIMR_PORT, sp->mmask); + + /* Read master to allow pics to settle */ + (void) inb(MIMR_PORT); + + /* Restore edge/level configuration for isa interupts */ + for (vecno = 0; vecno <= MAX_ISA_IRQ; vecno++) + psm_set_elcr(vecno, sp->elcr & (1 << vecno)); + + /* Reenter PIC mode before restoring LNK devices */ + (void) uppc_acpi_enter_picmode(); + + /* Restore ACPI link device mappings */ + acpi_restore_link_devices(); +} + +static int +uppc_state(psm_state_request_t *rp) +{ + switch (rp->psr_cmd) { + case PSM_STATE_ALLOC: + rp->req.psm_state_req.psr_state = + kmem_zalloc(sizeof (struct pic_state), KM_NOSLEEP); + if (rp->req.psm_state_req.psr_state == NULL) + return (ENOMEM); + rp->req.psm_state_req.psr_state_size = + sizeof (struct pic_state); + return (0); + case PSM_STATE_FREE: + kmem_free(rp->req.psm_state_req.psr_state, + rp->req.psm_state_req.psr_state_size); + return (0); + case PSM_STATE_SAVE: + pic_save_state(rp->req.psm_state_req.psr_state); + return (0); + case PSM_STATE_RESTORE: + pic_restore_state(rp->req.psm_state_req.psr_state); + return (0); + default: + return (EINVAL); + } +} + + static int uppc_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, int ipin, int *pci_irqp, iflag_t *intr_flagp) diff --git a/usr/src/uts/intel/io/acpica/acpica.c b/usr/src/uts/intel/io/acpica/acpica.c index 25b6f1dab7..283e06a164 100644 --- a/usr/src/uts/intel/io/acpica/acpica.c +++ b/usr/src/uts/intel/io/acpica/acpica.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* @@ -697,5 +697,5 @@ acpica_ddi_restore_resources(dev_info_t *dip) resbuf.Length = proplen; (void) AcpiSetCurrentResources(devobj, &resbuf); ddi_prop_free(propdata); - (void) ddi_prop_remove(DDI_DEV_T_ANY, dip, "acpi-crs"); + (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "acpi-crs"); } diff --git a/usr/src/uts/intel/io/dktp/controller/ata/ata_common.c b/usr/src/uts/intel/io/dktp/controller/ata/ata_common.c index 6de3774329..b18f3a12bf 100644 --- a/usr/src/uts/intel/io/dktp/controller/ata/ata_common.c +++ b/usr/src/uts/intel/io/dktp/controller/ata/ata_common.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -3551,12 +3551,12 @@ ata_resume_drive(ata_drv_t *ata_drvp) if (!ATAPIDRV(ata_drvp)) { /* Reset Ultra DMA mode */ - (void) ata_set_dma_mode(ata_ctlp, ata_drvp); + ata_reset_dma_mode(ata_drvp); if (!ata_disk_setup_parms(ata_ctlp, ata_drvp)) return; } else { (void) atapi_init_drive(ata_drvp); - (void) atapi_reset_dma_mode(ata_drvp); + atapi_reset_dma_mode(ata_drvp); } (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_DIS_REVPOD, 0); @@ -3858,3 +3858,36 @@ ata_set_dma_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp) return (rval); } + +/* + * Reset Ultra DMA mode / MWDMA mode + */ +void +ata_reset_dma_mode(ata_drv_t *ata_drvp) +{ + uint8_t subcmd; + int mode; + ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp; + + switch (ata_drvp->ad_dma_cap) { + case ATA_DMA_ULTRAMODE: + subcmd = ATF_XFRMOD_UDMA; + for (mode = 0; mode <= 6; mode++) { + if (ata_drvp->ad_dma_mode & (1 << (mode + 8))) + break; + } + break; + case ATA_DMA_MWORDMODE: + subcmd = ATF_XFRMOD_MDMA; + mode = ((ata_drvp->ad_dma_mode & ATAC_MDMA_2_SEL) == + ATAC_MDMA_2_SEL ? 2 : + (ata_drvp->ad_dma_mode & ATAC_MDMA_1_SEL) == + ATAC_MDMA_1_SEL ? 1 : 0); + break; + default: + return; + } + + (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_SET_XFRMOD, + (subcmd | mode)); +} diff --git a/usr/src/uts/intel/io/dktp/controller/ata/ata_common.h b/usr/src/uts/intel/io/dktp/controller/ata/ata_common.h index 79617958e7..2df68e08bf 100644 --- a/usr/src/uts/intel/io/dktp/controller/ata/ata_common.h +++ b/usr/src/uts/intel/io/dktp/controller/ata/ata_common.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -684,6 +684,7 @@ int ata_wait3(ddi_acc_handle_t io_hdl, caddr_t ioaddr, uchar_t onbits1, int ata_test_lba_support(struct ata_id *aidp); void ata_nsecwait(clock_t count); int ata_set_dma_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp); +void ata_reset_dma_mode(ata_drv_t *ata_drvp); void atapi_reset_dma_mode(ata_drv_t *ata_drvp); diff --git a/usr/src/uts/intel/io/dktp/controller/ata/atapi.c b/usr/src/uts/intel/io/dktp/controller/ata/atapi.c index d5a2b7d5c8..1715c516e0 100644 --- a/usr/src/uts/intel/io/dktp/controller/ata/atapi.c +++ b/usr/src/uts/intel/io/dktp/controller/ata/atapi.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1208,31 +1208,8 @@ atapi_init_arq( void atapi_reset_dma_mode(ata_drv_t *ata_drvp) { - uint8_t subcmd; - int mode; ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp; - switch (ata_drvp->ad_dma_cap) { - case ATA_DMA_ULTRAMODE: - subcmd = ATF_XFRMOD_UDMA; - for (mode = 0; mode <= 6; mode++) { - if (ata_drvp->ad_dma_mode & (1 << (mode + 8))) - break; - } - break; - case ATA_DMA_MWORDMODE: - subcmd = ATF_XFRMOD_MDMA; - mode = ((ata_drvp->ad_dma_mode & ATAC_MDMA_2_SEL) == - ATAC_MDMA_2_SEL ? 2 : - (ata_drvp->ad_dma_mode & ATAC_MDMA_1_SEL) == - ATAC_MDMA_1_SEL ? 1 : 0); - break; - default: - return; - } - - (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_SET_XFRMOD, - (subcmd | mode)); - + ata_reset_dma_mode(ata_drvp); (void) atapi_id_update(ata_ctlp, ata_drvp, NULL); } |