diff options
Diffstat (limited to 'usr/src/uts/intel')
-rw-r--r-- | usr/src/uts/intel/Makefile.files | 3 | ||||
-rw-r--r-- | usr/src/uts/intel/Makefile.intel.shared | 1 | ||||
-rw-r--r-- | usr/src/uts/intel/ia32/ml/modstubs.s | 2 | ||||
-rw-r--r-- | usr/src/uts/intel/io/acpica/acpica.c | 211 | ||||
-rw-r--r-- | usr/src/uts/intel/io/agpgart/amd64_gart.c | 24 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/controller/ata/ata_cmd.h | 5 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/controller/ata/ata_common.c | 632 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/controller/ata/ata_common.h | 15 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/dcdev/dadk.c | 162 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/disk/cmdk.c | 225 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/hba/ghd/ghd_debug.c | 21 | ||||
-rw-r--r-- | usr/src/uts/intel/io/pci/pci_pci.c | 56 | ||||
-rw-r--r-- | usr/src/uts/intel/io/vgatext/vgatext.c | 219 | ||||
-rw-r--r-- | usr/src/uts/intel/os/cpr_intel.c | 75 | ||||
-rw-r--r-- | usr/src/uts/intel/os/name_to_major | 2 | ||||
-rw-r--r-- | usr/src/uts/intel/promif/prom_env.c | 23 | ||||
-rwxr-xr-x | usr/src/uts/intel/srn/Makefile | 84 | ||||
-rw-r--r-- | usr/src/uts/intel/sys/acpica.h | 2 | ||||
-rw-r--r-- | usr/src/uts/intel/sys/promif.h | 10 |
19 files changed, 1433 insertions, 339 deletions
diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files index c84c1608c3..e4b136dd18 100644 --- a/usr/src/uts/intel/Makefile.files +++ b/usr/src/uts/intel/Makefile.files @@ -274,3 +274,6 @@ BOOTDEV_OBJS += \ bootdev.o INC_PATH += -I$(UTSBASE)/intel + + +CPR_INTEL_OBJS += cpr_intel.o diff --git a/usr/src/uts/intel/Makefile.intel.shared b/usr/src/uts/intel/Makefile.intel.shared index 53267390d6..4602092e15 100644 --- a/usr/src/uts/intel/Makefile.intel.shared +++ b/usr/src/uts/intel/Makefile.intel.shared @@ -208,6 +208,7 @@ DRV_KMODS += ahci DRV_KMODS += amd64_gart DRV_KMODS += amr DRV_KMODS += agpgart +DRV_KMODS += srn DRV_KMODS += agptarget DRV_KMODS += arp DRV_KMODS += asy diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s index d6d1bc3d58..d6f06c6e1f 100644 --- a/usr/src/uts/intel/ia32/ml/modstubs.s +++ b/usr/src/uts/intel/ia32/ml/modstubs.s @@ -596,6 +596,8 @@ fcnname/**/_info: \ NO_UNLOAD_STUB(klmmod, lm_svc, nomod_zero); NO_UNLOAD_STUB(klmmod, lm_shutdown, nomod_zero); NO_UNLOAD_STUB(klmmod, lm_unexport, nomod_zero); + NO_UNLOAD_STUB(klmmod, lm_cprresume, nomod_zero); + NO_UNLOAD_STUB(klmmod, lm_cprsuspend, nomod_zero); NO_UNLOAD_STUB(klmmod, lm_safelock, nomod_zero); NO_UNLOAD_STUB(klmmod, lm_safemap, nomod_zero); NO_UNLOAD_STUB(klmmod, lm_has_sleep, nomod_zero); diff --git a/usr/src/uts/intel/io/acpica/acpica.c b/usr/src/uts/intel/io/acpica/acpica.c index b743d46504..98044e8e3d 100644 --- a/usr/src/uts/intel/io/acpica/acpica.c +++ b/usr/src/uts/intel/io/acpica/acpica.c @@ -38,6 +38,7 @@ #include <sys/ddi.h> #include <sys/sunddi.h> #include <sys/esunddi.h> +#include <sys/kstat.h> #include <sys/acpi/acpi.h> #include <sys/acpica.h> @@ -57,10 +58,17 @@ static struct modlinkage modlinkage = { }; /* + * Local prototypes + */ + +static void acpica_init_kstats(void); + +/* * Local data */ static kmutex_t acpica_module_lock; +static kstat_t *acpica_ksp; /* * State of acpica subsystem @@ -99,17 +107,23 @@ int acpica_muzzle_debug_output = 0; int acpica_muzzle_debug_output = 1; #endif +/* + * ACPI DDI hooks + */ +static int acpica_ddi_setwake(dev_info_t *dip, int level); int _init(void) { int error = EBUSY; int status; + extern int (*acpi_fp_setwake)(); mutex_init(&acpica_module_lock, NULL, MUTEX_DRIVER, NULL); if ((error = mod_install(&modlinkage)) != 0) { mutex_destroy(&acpica_module_lock); + goto load_error; } AcpiGbl_EnableInterpreterSlack = (acpica_enable_interpreter_slack != 0); @@ -118,6 +132,9 @@ _init(void) cmn_err(CE_WARN, "!acpica: error pre-init:1:%d", status); } + acpi_fp_setwake = acpica_ddi_setwake; + +load_error: return (error); } @@ -388,6 +405,7 @@ acpica_init() acpica_ec_init(); acpica_init_state = ACPICA_INITIALIZED; + acpica_init_kstats(); error: if (acpica_init_state != ACPICA_INITIALIZED) { cmn_err(CE_NOTE, "!failed to initialize" @@ -487,3 +505,196 @@ acpica_get_sci(int *sci_irq, iflag_t *sci_flags) return (AE_OK); } + +/* + * Sets ACPI wake state for device referenced by dip. + * If level is S0 (0), disables wake event; otherwise, + * enables wake event which will wake system from level. + */ +static int +acpica_ddi_setwake(dev_info_t *dip, int level) +{ + ACPI_STATUS status; + ACPI_HANDLE devobj, gpeobj; + ACPI_OBJECT *prw, *gpe; + ACPI_BUFFER prw_buf; + int gpebit, pwr_res_count, prw_level, rv; + + /* + * initialize these early so we can use a common + * exit point below + */ + prw_buf.Pointer = NULL; + prw_buf.Length = ACPI_ALLOCATE_BUFFER; + rv = 0; + + /* + * Attempt to get a handle to a corresponding ACPI object. + * If no object is found, return quietly, since not all + * devices have corresponding ACPI objects. + */ + status = acpica_get_handle(dip, &devobj); + if (ACPI_FAILURE(status)) { + char pathbuf[MAXPATHLEN]; + ddi_pathname(dip, pathbuf); +#ifdef DEBUG + cmn_err(CE_NOTE, "!acpica_ddi_setwake: could not get" + " handle for %s, %s:%d", pathbuf, ddi_driver_name(dip), + ddi_get_instance(dip)); +#endif + goto done; + } + + /* + * Attempt to evaluate _PRW object. + * If no valid object is found, return quietly, since not all + * devices have _PRW objects. + */ + status = AcpiEvaluateObject(devobj, "_PRW", NULL, &prw_buf); + prw = prw_buf.Pointer; + if (ACPI_FAILURE(status) || prw == NULL || + prw->Type != ACPI_TYPE_PACKAGE || prw->Package.Count < 2 || + prw->Package.Elements[1].Type != ACPI_TYPE_INTEGER) { + cmn_err(CE_NOTE, "acpica_ddi_setwake: could not " + " evaluate _PRW"); + goto done; + } + + /* fetch the lowest wake level from the _PRW */ + prw_level = prw->Package.Elements[1].Integer.Value; + + /* + * process the GPE description + */ + switch (prw->Package.Elements[0].Type) { + case ACPI_TYPE_INTEGER: + gpeobj = NULL; + gpebit = prw->Package.Elements[0].Integer.Value; + break; + case ACPI_TYPE_PACKAGE: + gpe = &prw->Package.Elements[0]; + if (gpe->Package.Count != 2 || + gpe->Package.Elements[1].Type != ACPI_TYPE_INTEGER) + goto done; + gpeobj = gpe->Package.Elements[0].Reference.Handle; + gpebit = gpe->Package.Elements[1].Integer.Value; + if (gpeobj == NULL) + goto done; + default: + goto done; + } + + rv = -1; + if (level == 0) { + if (ACPI_FAILURE(AcpiDisableGpe(gpeobj, gpebit, ACPI_NOT_ISR))) + goto done; + } else if (prw_level <= level) { + if (ACPI_SUCCESS( + AcpiSetGpeType(gpeobj, gpebit, ACPI_GPE_TYPE_WAKE))) + if (ACPI_FAILURE( + AcpiEnableGpe(gpeobj, gpebit, ACPI_NOT_ISR))) + goto done; + } + rv = 0; +done: + if (prw_buf.Pointer != NULL) + AcpiOsFree(prw_buf.Pointer); + return (rv); +} + +/* + * kstat access to a limited set of ACPI propertis + */ +static void +acpica_init_kstats() +{ + ACPI_HANDLE s3handle; + ACPI_STATUS status; + FADT_DESCRIPTOR *fadt; + kstat_named_t *knp; + + /* + * Create a small set of named kstats; just return in the rare + * case of a failure, * in which case, the kstats won't be present. + */ + if ((acpica_ksp = kstat_create("acpi", 0, "acpi", "misc", + KSTAT_TYPE_NAMED, 2, 0)) == NULL) + return; + + /* + * initialize kstat 'S3' to reflect the presence of \_S3 in + * the ACPI namespace (1 = present, 0 = not present) + */ + knp = acpica_ksp->ks_data; + knp->value.l = (AcpiGetHandle(NULL, "\\_S3", &s3handle) == AE_OK); + kstat_named_init(knp, "S3", KSTAT_DATA_LONG); + knp++; /* advance to next named kstat */ + + /* + * initialize kstat 'preferred_pm_profile' to the value + * contained in the (always present) FADT + */ + status = AcpiGetFirmwareTable(FADT_SIG, 1, ACPI_LOGICAL_ADDRESSING, + (ACPI_TABLE_HEADER **)&fadt); + knp->value.l = (status == AE_OK) ? fadt->Prefer_PM_Profile : -1; + kstat_named_init(knp, "preferred_pm_profile", KSTAT_DATA_LONG); + + /* + * install the named kstats + */ + kstat_install(acpica_ksp); +} + +/* + * Attempt to save the current ACPI settings (_CRS) for the device + * which corresponds to the supplied devinfo node. The settings are + * saved as a property on the dip. If no ACPI object is found to be + * associated with the devinfo node, no action is taken and no error + * is reported. + */ +void +acpica_ddi_save_resources(dev_info_t *dip) +{ + ACPI_HANDLE devobj; + ACPI_BUFFER resbuf; + int ret; + + resbuf.Length = ACPI_ALLOCATE_BUFFER; + if (ACPI_FAILURE(acpica_get_handle(dip, &devobj)) || + ACPI_FAILURE(AcpiGetCurrentResources(devobj, &resbuf))) + return; + + ret = ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, + "acpi-crs", resbuf.Pointer, resbuf.Length); + + ASSERT(ret == DDI_PROP_SUCCESS); + + AcpiOsFree(resbuf.Pointer); +} + +/* + * If the supplied devinfo node has an ACPI settings property attached, + * restore them to the associated ACPI device using _SRS. The property + * is deleted from the devinfo node afterward. + */ +void +acpica_ddi_restore_resources(dev_info_t *dip) +{ + ACPI_HANDLE devobj; + ACPI_BUFFER resbuf; + uchar_t *propdata; + uint_t proplen; + + if (ACPI_FAILURE(acpica_get_handle(dip, &devobj))) + return; + + if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, + "acpi-crs", &propdata, &proplen) != DDI_PROP_SUCCESS) + return; + + resbuf.Pointer = propdata; + resbuf.Length = proplen; + (void) AcpiSetCurrentResources(devobj, &resbuf); + ddi_prop_free(propdata); + (void) ddi_prop_remove(DDI_DEV_T_ANY, dip, "acpi-crs"); +} diff --git a/usr/src/uts/intel/io/agpgart/amd64_gart.c b/usr/src/uts/intel/io/agpgart/amd64_gart.c index fbcebf781d..22d6ef3994 100644 --- a/usr/src/uts/intel/io/agpgart/amd64_gart.c +++ b/usr/src/uts/intel/io/agpgart/amd64_gart.c @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -173,9 +173,18 @@ amd64_gart_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) int status; char buf[80]; - if (cmd != DDI_ATTACH) + switch (cmd) { + default: return (DDI_FAILURE); + case DDI_RESUME: + /* Nothing special is needed for resume. */ + return (DDI_SUCCESS); + + case DDI_ATTACH: + break; + } + instance = ddi_get_instance(dip); if (ddi_soft_state_zalloc(amd64_gart_glob_soft_handle, instance) != @@ -209,9 +218,18 @@ amd64_gart_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) amd64_gart_softstate_t *sc; char buf[80]; - if (cmd != DDI_DETACH) + switch (cmd) { + default: return (DDI_FAILURE); + case DDI_SUSPEND: + /* Nothing special is needed for suspend */ + return (DDI_SUCCESS); + + case DDI_DETACH: + break; + } + instance = ddi_get_instance(dip); sc = ddi_get_soft_state(amd64_gart_glob_soft_handle, instance); diff --git a/usr/src/uts/intel/io/dktp/controller/ata/ata_cmd.h b/usr/src/uts/intel/io/dktp/controller/ata/ata_cmd.h index 9483f1e9b0..3607ff1cda 100644 --- a/usr/src/uts/intel/io/dktp/controller/ata/ata_cmd.h +++ b/usr/src/uts/intel/io/dktp/controller/ata/ata_cmd.h @@ -2,7 +2,7 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). + * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE @@ -20,7 +20,7 @@ */ /* - * Copyright 1996 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,6 +45,7 @@ extern "C" { #define ATC_DOOR_LOCK 0xde /* door lock */ #define ATC_DOOR_UNLOCK 0xdf /* door unlock */ #define ATC_IDLE 0xe3 /* idle */ +#define ATC_SLEEP 0xe6 /* sleep */ /* * ATA/ATAPI-4 disk commands. 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 17294569fb..7fb8da9ff0 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 @@ -99,6 +99,12 @@ static int ata_check_revert_to_defaults(ata_drv_t *ata_drvp); static void ata_show_transfer_mode(ata_ctl_t *, ata_drv_t *); static int ata_spec_init_controller(dev_info_t *dip); +static void ata_init_pm(dev_info_t *); +static int ata_suspend(dev_info_t *); +static int ata_resume(dev_info_t *); +static int ata_power(dev_info_t *, int, int); +static int ata_change_power(dev_info_t *, uint8_t); +static int ata_is_pci(dev_info_t *); /* * Local static data @@ -114,6 +120,21 @@ int ata_reset_bus_watchdog = 1000; /* + * Use local or framework power management + */ + +#ifdef ATA_USE_AUTOPM +#define ATA_BUSY_COMPONENT(d, c) ((void)pm_busy_component(d, c)) +#define ATA_IDLE_COMPONENT(d, c) ((void)pm_idle_component(d, c)) +#define ATA_RAISE_POWER(d, c, l) pm_raise_power(d, c, l) +#define ATA_LOWER_POWER(d, c, l) pm_lower_power(d, c, l) +#else +#define ATA_BUSY_COMPONENT(d, c) +#define ATA_IDLE_COMPONENT(d, c) +#define ATA_RAISE_POWER(d, c, l) ata_power(d, c, l) +#define ATA_LOWER_POWER(d, c, l) ata_power(d, c, l) +#endif +/* * number of seconds to wait during various operations */ int ata_flush_delay = 5 * 1000000; @@ -228,7 +249,8 @@ ata_devo_reset( if ((ata_drvp->ad_flags & AD_DISK) != 0 && ((ata_drvp->ad_flags & AD_NORVRT) == 0)) { /* Enable revert to defaults when reset */ - (void) ata_set_feature(ata_ctlp, ata_drvp, 0xCC, 0); + (void) ata_set_feature(ata_ctlp, ata_drvp, + ATSF_ENA_REVPOD, 0); } /* @@ -245,7 +267,7 @@ ata_devo_reset( */ rc = ata_flush_cache(ata_ctlp, ata_drvp); ADBG_WARN(("ata_flush_cache %s\n", - rc ? "okay" : "failed")); + rc ? "okay" : "failed")); if (!rc) flush_okay = FALSE; @@ -297,7 +319,8 @@ static struct dev_ops ata_ops = { ata_detach, /* detach */ ata_devo_reset, /* reset */ &ata_cb_ops, /* driver operations */ - NULL /* bus operations */ + NULL, /* bus operations */ + ata_power /* power */ }; /* driver loadable module wrapper */ @@ -419,8 +442,14 @@ ata_attach( debug_enter("\nATA_ATTACH\n\n"); #endif - if (cmd != DDI_ATTACH) + switch (cmd) { + case DDI_ATTACH: + break; + case DDI_RESUME: + return (ata_resume(dip)); + default: return (DDI_FAILURE); + } /* initialize controller */ ata_ctlp = ata_init_controller(dip); @@ -476,14 +505,14 @@ ata_attach( * confused by non-existent drives. */ ddi_put8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_drvhd, - first_drvp->ad_drive_bits); + first_drvp->ad_drive_bits); ata_nsecwait(400); /* * make certain the drive selected */ if (!ata_wait(ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2, - 0, ATS_BSY, 5000000)) { + 0, ATS_BSY, 5000000)) { ADBG_ERROR(("ata_attach: select failed\n")); } @@ -525,6 +554,8 @@ ata_attach( ata_ctlp->ac_flags |= AC_ATTACHED; mutex_exit(&ata_ctlp->ac_ccc.ccc_hba_mutex); + ata_init_pm(dip); + ddi_report_dev(dip); return (DDI_SUCCESS); @@ -550,8 +581,14 @@ ata_detach( ADBG_TRACE(("ata_detach entered\n")); - if (cmd != DDI_DETACH) + switch (cmd) { + case DDI_DETACH: + break; + case DDI_SUSPEND: + return (ata_suspend(dip)); + default: return (DDI_FAILURE); + } instance = ddi_get_instance(dip); ata_ctlp = ddi_get_soft_state(ata_state, instance); @@ -559,6 +596,17 @@ ata_detach( if (!ata_ctlp) return (DDI_SUCCESS); + if (ata_ctlp->ac_pm_support) { + ATA_BUSY_COMPONENT(dip, 0); + if (ata_ctlp->ac_pm_level != PM_LEVEL_D0) { + if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) != + DDI_SUCCESS) { + ATA_IDLE_COMPONENT(dip, 0); + return (DDI_FAILURE); + } + } + (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components"); + } ata_ctlp->ac_flags &= ~AC_ATTACHED; /* destroy ata module */ @@ -641,8 +689,8 @@ ata_bus_ctl( /* These ops shouldn't be called by a target driver */ ADBG_ERROR(("ata_bus_ctl: %s%d: invalid op (%d) from %s%d\n", - ddi_driver_name(d), ddi_get_instance(d), o, - ddi_driver_name(r), ddi_get_instance(r))); + ddi_driver_name(d), ddi_get_instance(d), o, + ddi_driver_name(r), ddi_get_instance(r))); return (DDI_FAILURE); @@ -683,7 +731,7 @@ ata_bus_ctl( target_type = ATA_DEV_ATAPI; else { ADBG_WARN(("ata_bus_ctl: invalid target class %s\n", - bufp)); + bufp)); ddi_prop_free(bufp); return (DDI_FAILURE); } @@ -710,17 +758,17 @@ ata_bus_ctl( /* get (target,lun) of child device */ targ = ddi_prop_get_int(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS, - "target", -1); + "target", -1); if (targ == -1) { ADBG_WARN(("ata_bus_ctl: failed to get targ num\n")); return (DDI_FAILURE); } lun = ddi_prop_get_int(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS, - "lun", 0); + "lun", 0); if ((targ < 0) || (targ >= ATA_MAXTARG) || - (lun < 0) || (lun >= ATA_MAXLUN)) { + (lun < 0) || (lun >= ATA_MAXLUN)) { return (DDI_FAILURE); } @@ -743,7 +791,7 @@ ata_bus_ctl( if (strcmp(ddi_get_name(tdip), "cmdk") == 0) { if ((target_type == ATA_DEV_DISK) && - (target_type != drive_type)) + (target_type != drive_type)) return (DDI_FAILURE); target_type = drive_type; @@ -757,9 +805,9 @@ ata_bus_ctl( if (ndi_prop_update_string(DDI_DEV_T_NONE, tdip, "disk", disk_prop) != DDI_PROP_SUCCESS) { ADBG_WARN(("ata_bus_ctl: failed to " - "create disk prop\n")); + "create disk prop\n")); return (DDI_FAILURE); - } + } } if (ndi_prop_update_string(DDI_DEV_T_NONE, tdip, @@ -820,7 +868,7 @@ ata_hba_complete( ata_pktp = GCMD2APKT(gcmdp); if (ata_pktp->ap_complete) (*ata_pktp->ap_complete)(ata_drvp, ata_pktp, - do_callback); + do_callback); } /* GHD ccc_timeout_func callback */ @@ -919,7 +967,7 @@ ata_init_controller( if (ata_ctlp == NULL) { ADBG_WARN(("ata_init_controller: failed to find " - "controller struct\n")); + "controller struct\n")); return (NULL); } @@ -933,14 +981,14 @@ ata_init_controller( * map the device registers */ if (!ata_setup_ioaddr(dip, &ata_ctlp->ac_iohandle1, &ioaddr1, - &ata_ctlp->ac_iohandle2, &ioaddr2, - &ata_ctlp->ac_bmhandle, &ata_ctlp->ac_bmaddr)) { + &ata_ctlp->ac_iohandle2, &ioaddr2, + &ata_ctlp->ac_bmhandle, &ata_ctlp->ac_bmaddr)) { (void) ata_detach(dip, DDI_DETACH); return (NULL); } ADBG_INIT(("ata_init_controller: ioaddr1 = 0x%p, ioaddr2 = 0x%p\n", - ioaddr1, ioaddr2)); + ioaddr1, ioaddr2)); /* * Do ARQ setup @@ -980,12 +1028,12 @@ ata_init_controller( * drop after a resume. */ ata_ctlp->ac_timing_flags = ddi_prop_get_int(DDI_DEV_T_ANY, - dip, DDI_PROP_DONTPASS, "timing_flags", 0); + dip, DDI_PROP_DONTPASS, "timing_flags", 0); /* * get max transfer size, default to 256 sectors */ ata_ctlp->ac_max_transfer = ddi_prop_get_int(DDI_DEV_T_ANY, - dip, DDI_PROP_DONTPASS, "max_transfer", 0x100); + dip, DDI_PROP_DONTPASS, "max_transfer", 0x100); if (ata_ctlp->ac_max_transfer < 1) ata_ctlp->ac_max_transfer = 1; if (ata_ctlp->ac_max_transfer > 0x100) @@ -995,7 +1043,7 @@ ata_init_controller( * Get the standby timer value */ ata_ctlp->ac_standby_time = ddi_prop_get_int(DDI_DEV_T_ANY, - dip, DDI_PROP_DONTPASS, "standby", -1); + dip, DDI_PROP_DONTPASS, "standby", -1); /* * If this is a /pci/pci-ide instance check to see if @@ -1011,9 +1059,9 @@ ata_init_controller( return (NULL); } (void) sprintf(prop_buf, "SUNW-ata-%04x-isa", - addr1); + addr1); if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), - DDI_PROP_DONTPASS, prop_buf)) { + DDI_PROP_DONTPASS, prop_buf)) { (void) ata_detach(dip, DDI_DETACH); return (NULL); } @@ -1029,11 +1077,11 @@ ata_init_controller( GHD_WAITQ_INIT(&ata_ctlp->ac_ccc.ccc_waitq, NULL, 1); if (!ghd_register("ata", &ata_ctlp->ac_ccc, dip, 0, ata_ctlp, - atapi_ccballoc, atapi_ccbfree, - ata_pciide_dma_sg_func, ata_hba_start, - ata_hba_complete, ata_intr, - ata_get_status, ata_process_intr, ata_timeout_func, - &ata_timer_conf, NULL)) { + atapi_ccballoc, atapi_ccbfree, + ata_pciide_dma_sg_func, ata_hba_start, + ata_hba_complete, ata_intr, + ata_get_status, ata_process_intr, ata_timeout_func, + &ata_timer_conf, NULL)) { (void) ata_detach(dip, DDI_DETACH); return (NULL); } @@ -1094,7 +1142,7 @@ ata_init_drive( int valid_version = 0; ADBG_TRACE(("ata_init_drive entered, targ = %d, lun = %d\n", - targ, lun)); + targ, lun)); /* check if device already exists */ @@ -1114,7 +1162,7 @@ ata_init_drive( ata_drvp->ad_ctlp = ata_ctlp; ata_drvp->ad_targ = targ; ata_drvp->ad_drive_bits = - (ata_drvp->ad_targ == 0 ? ATDH_DRIVE0 : ATDH_DRIVE1); + (ata_drvp->ad_targ == 0 ? ATDH_DRIVE0 : ATDH_DRIVE1); /* * Add the LUN for SFF-8070i support */ @@ -1127,11 +1175,11 @@ ata_init_drive( */ drive_type = ata_drive_type(ata_drvp->ad_drive_bits, - ata_ctlp->ac_iohandle1, - ata_ctlp->ac_ioaddr1, - ata_ctlp->ac_iohandle2, - ata_ctlp->ac_ioaddr2, - aidp); + ata_ctlp->ac_iohandle1, + ata_ctlp->ac_ioaddr1, + ata_ctlp->ac_iohandle2, + ata_ctlp->ac_ioaddr2, + aidp); switch (drive_type) { case ATA_DEV_NONE: @@ -1150,11 +1198,11 @@ ata_init_drive( */ if (!ata_strncmp(nec_260, aidp->ai_model, sizeof (aidp->ai_model))) { swab(aidp->ai_drvser, aidp->ai_drvser, - sizeof (aidp->ai_drvser)); + sizeof (aidp->ai_drvser)); swab(aidp->ai_fw, aidp->ai_fw, - sizeof (aidp->ai_fw)); + sizeof (aidp->ai_fw)); swab(aidp->ai_model, aidp->ai_model, - sizeof (aidp->ai_model)); + sizeof (aidp->ai_model)); } /* @@ -1177,8 +1225,8 @@ ata_init_drive( buf[i] = '\0'; ATAPRT(("?\t%s device at targ %d, lun %d lastlun 0x%x\n", - (ATAPIDRV(ata_drvp) ? "ATAPI":"IDE"), - ata_drvp->ad_targ, ata_drvp->ad_lun, aidp->ai_lastlun)); + (ATAPIDRV(ata_drvp) ? "ATAPI":"IDE"), + ata_drvp->ad_targ, ata_drvp->ad_lun, aidp->ai_lastlun)); ATAPRT(("?\tmodel %s\n", buf)); @@ -1191,21 +1239,21 @@ ata_init_drive( } ATAPRT(( "?\tATA/ATAPI-%d supported, majver 0x%x minver 0x%x\n", - valid_version, - aidp->ai_majorversion, - aidp->ai_minorversion)); + valid_version, + aidp->ai_majorversion, + aidp->ai_minorversion)); } if (ata_capability_data) { ATAPRT(("?\t\tstat %x, err %x\n", - ddi_get8(ata_ctlp->ac_iohandle2, - ata_ctlp->ac_altstatus), - ddi_get8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_error))); + ddi_get8(ata_ctlp->ac_iohandle2, + ata_ctlp->ac_altstatus), + ddi_get8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_error))); ATAPRT(("?\t\tcfg 0x%x, cap 0x%x\n", - aidp->ai_config, - aidp->ai_cap)); + aidp->ai_config, + aidp->ai_cap)); /* * Be aware that ATA-6 and later drives may not provide valid @@ -1220,34 +1268,34 @@ ata_init_drive( * Supported version less then ATA-6 */ ATAPRT(("?\t\tcyl %d, hd %d, sec/trk %d\n", - aidp->ai_fixcyls, - aidp->ai_heads, - aidp->ai_sectors)); + aidp->ai_fixcyls, + aidp->ai_heads, + aidp->ai_sectors)); } ATAPRT(("?\t\tmult1 0x%x, mult2 0x%x\n", - aidp->ai_mult1, - aidp->ai_mult2)); + aidp->ai_mult1, + aidp->ai_mult2)); if (valid_version && aidp->ai_majorversion < ATAC_MAJVER_4) { ATAPRT(( "?\t\tpiomode 0x%x, dmamode 0x%x, advpiomode 0x%x\n", - aidp->ai_piomode, - aidp->ai_dmamode, - aidp->ai_advpiomode)); + aidp->ai_piomode, + aidp->ai_dmamode, + aidp->ai_advpiomode)); } else { ATAPRT(("?\t\tadvpiomode 0x%x\n", - aidp->ai_advpiomode)); + aidp->ai_advpiomode)); } ATAPRT(("?\t\tminpio %d, minpioflow %d\n", - aidp->ai_minpio, - aidp->ai_minpioflow)); + aidp->ai_minpio, + aidp->ai_minpioflow)); if (valid_version && aidp->ai_majorversion >= ATAC_MAJVER_4 && (aidp->ai_validinfo & ATAC_VALIDINFO_83)) { ATAPRT(("?\t\tdwdma 0x%x, ultradma 0x%x\n", - aidp->ai_dworddma, - aidp->ai_ultradma)); + aidp->ai_dworddma, + aidp->ai_ultradma)); } else { ATAPRT(("?\t\tdwdma 0x%x\n", - aidp->ai_dworddma)); + aidp->ai_dworddma)); } } @@ -1268,7 +1316,7 @@ ata_init_drive( * lock the drive's current settings in case I have to * reset the drive due to some sort of error */ - (void) ata_set_feature(ata_ctlp, ata_drvp, 0x66, 0); + (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_DIS_REVPOD, 0); return (ata_drvp); @@ -1299,14 +1347,14 @@ ata_uninit_drive( * Select the correct drive */ ddi_put8(ata_ctlp->ac_iohandle1, ata_ctlp->ac_drvhd, - ata_drvp->ad_drive_bits); + ata_drvp->ad_drive_bits); ata_nsecwait(400); /* * Disable interrupts from the drive */ ddi_put8(ata_ctlp->ac_iohandle2, ata_ctlp->ac_devctl, - (ATDC_D3 | ATDC_NIEN)); + (ATDC_D3 | ATDC_NIEN)); #endif /* interface specific clean-ups */ @@ -1352,7 +1400,7 @@ ata_drive_type( * make certain the drive is selected, and wait for not busy */ (void) ata_wait3(io_hdl2, ioaddr2, 0, ATS_BSY, 0x7f, 0, 0x7f, 0, - 5 * 1000000); + 5 * 1000000); status = ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS); @@ -1481,12 +1529,12 @@ ata_wait3( * check for error conditions */ if ((val & failure_onbits2) == failure_onbits2 && - (val & failure_offbits2) == 0) { + (val & failure_offbits2) == 0) { return (FALSE); } if ((val & failure_onbits3) == failure_onbits3 && - (val & failure_offbits3) == 0) { + (val & failure_offbits3) == 0) { return (FALSE); } @@ -1564,7 +1612,7 @@ ata_id_common( * make sure we give them enough time to respond. */ (void) ata_wait3(io_hdl2, ioaddr2, 0, ATS_BSY, - ATS_ERR, ATS_BSY, 0x7f, 0, 5 * 1000000); + ATS_ERR, ATS_BSY, 0x7f, 0, 5 * 1000000); /* * read the status byte and clear the pending interrupt @@ -1581,8 +1629,8 @@ ata_id_common( if (status & ATS_BSY) { ADBG_ERROR(("ata_id_common: BUSY status 0x%x error 0x%x\n", - ddi_get8(io_hdl2, (uchar_t *)ioaddr2 +AT_ALTSTATUS), - ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR))); + ddi_get8(io_hdl2, (uchar_t *)ioaddr2 +AT_ALTSTATUS), + ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR))); return (FALSE); } @@ -1596,8 +1644,8 @@ ata_id_common( */ if (!ata_wait(io_hdl2, ioaddr2, ATS_DRQ, ATS_BSY, 1000000)) { ADBG_WARN(("ata_id_common: !DRQ status 0x%x error 0x%x\n", - ddi_get8(io_hdl2, (uchar_t *)ioaddr2 +AT_ALTSTATUS), - ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR))); + ddi_get8(io_hdl2, (uchar_t *)ioaddr2 +AT_ALTSTATUS), + ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR))); return (FALSE); } } @@ -1606,7 +1654,7 @@ ata_id_common( * transfer the data */ ddi_rep_get16(io_hdl1, (ushort_t *)aidp, (ushort_t *)ioaddr1 + AT_DATA, - NBPSCTR >> 1, DDI_DEV_NO_AUTOINCR); + NBPSCTR >> 1, DDI_DEV_NO_AUTOINCR); /* wait for the busy bit to settle */ ata_nsecwait(400); @@ -1624,10 +1672,10 @@ ata_id_common( * */ if (!ata_wait(io_hdl2, ioaddr2, (uchar_t)(expect_drdy ? ATS_DRDY : 0), - (ATS_BSY | ATS_DRQ), 1000000)) { + (ATS_BSY | ATS_DRQ), 1000000)) { ADBG_WARN(("ata_id_common: bad status 0x%x error 0x%x\n", - ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS), - ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR))); + ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS), + ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR))); return (FALSE); } @@ -1639,8 +1687,8 @@ ata_id_common( */ if (status & (ATS_DF | ATS_ERR)) { ADBG_WARN(("ata_id_common: status 0x%x error 0x%x \n", - ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS), - ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR))); + ddi_get8(io_hdl2, (uchar_t *)ioaddr2 + AT_ALTSTATUS), + ddi_get8(io_hdl1, (uchar_t *)ioaddr1 + AT_ERROR))); return (FALSE); } return (TRUE); @@ -1677,13 +1725,13 @@ ata_command( /* make certain the drive selected */ if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2, - (uchar_t)(expect_drdy ? ATS_DRDY : 0), - ATS_BSY, busy_wait)) { + (uchar_t)(expect_drdy ? ATS_DRDY : 0), + ATS_BSY, busy_wait)) { ADBG_ERROR(("ata_command: select failed " - "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x " - "S 0x%x H 0x%x CL 0x%x CH 0x%x\n", - expect_drdy, cmd, feature, count, - sector, head, cyl_low, cyl_hi)); + "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x " + "S 0x%x H 0x%x CL 0x%x CH 0x%x\n", + expect_drdy, cmd, feature, count, + sector, head, cyl_low, cyl_hi)); return (FALSE); } @@ -1706,10 +1754,10 @@ ata_command( /* wait for not busy */ if (!ata_wait(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY, busy_wait)) { ADBG_ERROR(("ata_command: BSY too long!" - "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x " - "S 0x%x H 0x%x CL 0x%x CH 0x%x\n", - expect_drdy, cmd, feature, count, - sector, head, cyl_low, cyl_hi)); + "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x " + "S 0x%x H 0x%x CL 0x%x CH 0x%x\n", + expect_drdy, cmd, feature, count, + sector, head, cyl_low, cyl_hi)); return (FALSE); } @@ -1717,10 +1765,10 @@ ata_command( * wait for DRDY before continuing */ (void) ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2, - ATS_DRDY, ATS_BSY, /* okay */ - ATS_ERR, ATS_BSY, /* cmd failed */ - ATS_DF, ATS_BSY, /* drive failed */ - busy_wait); + ATS_DRDY, ATS_BSY, /* okay */ + ATS_ERR, ATS_BSY, /* cmd failed */ + ATS_DF, ATS_BSY, /* drive failed */ + busy_wait); /* read status to clear IRQ, and check for error */ status = ddi_get8(io_hdl1, ata_ctlp->ac_status); @@ -1730,12 +1778,12 @@ ata_command( if (!silent) { ADBG_ERROR(("ata_command status 0x%x error 0x%x " - "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x " - "S 0x%x H 0x%x CL 0x%x CH 0x%x\n", - ddi_get8(io_hdl1, ata_ctlp->ac_status), - ddi_get8(io_hdl1, ata_ctlp->ac_error), - expect_drdy, cmd, feature, count, - sector, head, cyl_low, cyl_hi)); + "DRDY 0x%x CMD 0x%x F 0x%x N 0x%x " + "S 0x%x H 0x%x CL 0x%x CH 0x%x\n", + ddi_get8(io_hdl1, ata_ctlp->ac_status), + ddi_get8(io_hdl1, ata_ctlp->ac_error), + expect_drdy, cmd, feature, count, + sector, head, cyl_low, cyl_hi)); } return (FALSE); } @@ -1758,8 +1806,8 @@ ata_set_feature( int rc; rc = ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, ata_set_feature_wait, - ATC_SET_FEAT, feature, value, 0, 0, 0, 0); - /* feature, count, sector, head, cyl_low, cyl_hi */ + ATC_SET_FEAT, feature, value, 0, 0, 0, 0); + /* feature, count, sector, head, cyl_low, cyl_hi */ if (rc) { return (TRUE); @@ -1784,8 +1832,8 @@ ata_flush_cache( { /* this command is optional so fail silently */ return (ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, - ata_flush_cache_wait, - ATC_FLUSH_CACHE, 0, 0, 0, 0, 0, 0)); + ata_flush_cache_wait, + ATC_FLUSH_CACHE, 0, 0, 0, 0, 0, 0)); } /* @@ -1812,7 +1860,6 @@ ata_setup_ioaddr( caddr_t *bm_addrp) { ddi_device_acc_attr_t dev_attr; - char *bufp; int rnumber; int rc; off_t regsize; @@ -1824,14 +1871,14 @@ ata_setup_ioaddr( rc = ddi_dev_regsize(dip, 0, ®size); if (rc != DDI_SUCCESS || regsize <= AT_CMD) { ADBG_INIT(("ata_setup_ioaddr(1): rc %d regsize %lld\n", - rc, (long long)regsize)); + rc, (long long)regsize)); return (FALSE); } rc = ddi_dev_regsize(dip, 1, ®size); if (rc != DDI_SUCCESS || regsize <= AT_ALTSTATUS) { ADBG_INIT(("ata_setup_ioaddr(2): rc %d regsize %lld\n", - rc, (long long)regsize)); + rc, (long long)regsize)); return (FALSE); } @@ -1859,24 +1906,15 @@ ata_setup_ioaddr( /* else, it's ISA or PCI-IDE, check further */ rnumber = 0; - rc = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "device_type", &bufp); - if (rc != DDI_PROP_SUCCESS) { - ADBG_ERROR(("ata_setup_ioaddr !device_type\n")); - goto not_pciide; - } - - if (strcmp(bufp, "pci-ide") != 0) { + if (!ata_is_pci(dip)) { /* * If it's not a PCI-IDE, there are only two reg tuples * and the first one contains the I/O base (170 or 1f0) * rather than the controller instance number. */ ADBG_TRACE(("ata_setup_ioaddr !pci-ide\n")); - ddi_prop_free(bufp); goto not_pciide; } - ddi_prop_free(bufp); /* @@ -1889,7 +1927,7 @@ ata_setup_ioaddr( rc = ddi_dev_regsize(dip, 2, ®size); if (rc != DDI_SUCCESS || regsize < 8) { ADBG_INIT(("ata_setup_ioaddr(3): rc %d regsize %lld\n", - rc, (long long)regsize)); + rc, (long long)regsize)); goto not_pciide; } @@ -1898,7 +1936,7 @@ ata_setup_ioaddr( if (rc != DDI_SUCCESS) { /* map failed, try to use in non-pci-ide mode */ ADBG_WARN(("ata_setup_ioaddr bus master map failed, rc=0x%x\n", - rc)); + rc)); *bm_hdlp = NULL; } @@ -1908,7 +1946,7 @@ not_pciide: */ rc = ddi_regs_map_setup(dip, rnumber, addr1p, 0, 0, &dev_attr, - handle1p); + handle1p); if (rc != DDI_SUCCESS) { cmn_err(CE_WARN, "ata: reg tuple 0 map failed, rc=0x%x\n", rc); @@ -1930,7 +1968,7 @@ not_pciide: * map the upper control block registers */ rc = ddi_regs_map_setup(dip, rnumber + 1, addr2p, 0, 0, &dev_attr, - handle2p); + handle2p); if (rc == DDI_SUCCESS) return (TRUE); @@ -2010,7 +2048,7 @@ ata_init_pciide( if (ata_check_pciide_blacklist(dip, ATA_BL_NODMA)) { ata_ctlp->ac_pciide_bm = FALSE; ata_cntrl_DMA_sel_msg = - "cntrl blacklisted/DMA engine broken"; + "cntrl blacklisted/DMA engine broken"; return; } @@ -2023,11 +2061,11 @@ ata_init_pciide( */ class_code = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "class-code", 0); + DDI_PROP_DONTPASS, "class-code", 0); if ((class_code & PCIIDE_BM_CAP_MASK) != PCIIDE_BM_CAP_MASK) { ata_ctlp->ac_pciide_bm = FALSE; ata_cntrl_DMA_sel_msg = - "cntrl not Bus Master DMA capable"; + "cntrl not Bus Master DMA capable"; return; } @@ -2036,7 +2074,7 @@ ata_init_pciide( * between channels */ status = ddi_get8(ata_ctlp->ac_bmhandle, - (uchar_t *)ata_ctlp->ac_bmaddr + PCIIDE_BMISX_REG); + (uchar_t *)ata_ctlp->ac_bmaddr + PCIIDE_BMISX_REG); /* * Some motherboards have CSB5's that are wired "to emulate CSB4 mode". * In such a mode, the simplex bit is asserted, but in fact testing @@ -2138,7 +2176,7 @@ ata_init_drive_pcidma( } ata_options = ddi_prop_get_int(DDI_DEV_T_ANY, ata_ctlp->ac_dip, - 0, "ata-options", 0); + 0, "ata-options", 0); if (!(ata_options & ATA_OPTIONS_DMA)) { /* @@ -2146,7 +2184,7 @@ ata_init_drive_pcidma( * DMA is not enabled by this property */ ata_dev_DMA_sel_msg = - "disabled by \"ata-options\" property"; + "disabled by \"ata-options\" property"; return (ATA_DMA_OFF); } @@ -2178,13 +2216,13 @@ ata_init_drive_pcidma( } dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip, - 0, "ata-dma-enabled", TRUE); + 0, "ata-dma-enabled", TRUE); disk_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip, - 0, "ata-disk-dma-enabled", TRUE); + 0, "ata-disk-dma-enabled", TRUE); cd_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip, - 0, "atapi-cd-dma-enabled", FALSE); + 0, "atapi-cd-dma-enabled", FALSE); atapi_dma = ata_prop_lookup_int(DDI_DEV_T_ANY, tdip, - 0, "atapi-other-dma-enabled", TRUE); + 0, "atapi-other-dma-enabled", TRUE); if (dma == FALSE) { cmn_err(CE_CONT, "?ata_init_drive_pcidma: " @@ -2288,7 +2326,7 @@ ata_prop_create( if (strcmp("atapi", name) == 0) { rc = ndi_prop_update_string(DDI_DEV_T_NONE, tgt_dip, - "variant", name); + "variant", name); if (rc != DDI_PROP_SUCCESS) return (FALSE); } @@ -2297,7 +2335,7 @@ ata_prop_create( return (TRUE); rc = ndi_prop_update_byte_array(DDI_DEV_T_NONE, tgt_dip, name, - (uchar_t *)&ata_drvp->ad_id, sizeof (ata_drvp->ad_id)); + (uchar_t *)&ata_drvp->ad_id, sizeof (ata_drvp->ad_id)); if (rc != DDI_PROP_SUCCESS) { ADBG_ERROR(("ata_prop_create failed, rc=%d\n", rc)); } @@ -2469,7 +2507,7 @@ ata_ctlr_fsm( * Start ARQ pkt if necessary */ if ((ata_pktp->ap_flags & AP_ARQ_NEEDED) == AP_ARQ_NEEDED && - (ata_pktp->ap_status & ATS_ERR)) { + (ata_pktp->ap_status & ATS_ERR)) { /* set controller state back to active */ ata_ctlp->ac_state = current_state; @@ -2552,7 +2590,7 @@ ata_start_arq( arq_pktp->ap_resid = senselen; arq_pktp->ap_flags = AP_ATAPI | AP_READ; arq_pktp->ap_cdb_pad = - ((unsigned)(ata_drvp->ad_cdb_len - arq_pktp->ap_cdb_len)) >> 1; + ((unsigned)(ata_drvp->ad_cdb_len - arq_pktp->ap_cdb_len)) >> 1; bytes = min(senselen, ATAPI_MAX_BYTES_PER_DRQ); arq_pktp->ap_hicyl = (uchar_t)(bytes >> 8); @@ -2591,7 +2629,7 @@ ata_reset_bus( fsm_func = ATA_FSM_RESET; for (watchdog = ata_reset_bus_watchdog; watchdog > 0; watchdog--) { switch (ata_ctlr_fsm(fsm_func, ata_ctlp, NULL, NULL, - &DoneFlg)) { + &DoneFlg)) { case ATA_FSM_RC_OKAY: rc = TRUE; goto fsm_done; @@ -2737,7 +2775,7 @@ wait_for_not_busy: */ usecs_left = (deadline - gethrtime()) / 1000; (void) ata_wait3(io_hdl2, ata_ctlp->ac_ioaddr2, 0, ATS_BSY, - ATS_ERR, ATS_BSY, ATS_DF, ATS_BSY, usecs_left); + ATS_ERR, ATS_BSY, ATS_DF, ATS_BSY, usecs_left); return (TRUE); } @@ -2987,7 +3025,7 @@ ata_hba_start( request_started = FALSE; for (watchdog = ata_hba_start_watchdog; watchdog > 0; watchdog--) { switch (ata_ctlr_fsm(fsm_func, ata_ctlp, ata_drvp, ata_pktp, - NULL)) { + NULL)) { case ATA_FSM_RC_OKAY: request_started = TRUE; goto fsm_done; @@ -3037,15 +3075,15 @@ ata_check_pciide_blacklist( vendorid = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "vendor-id", 0); + DDI_PROP_DONTPASS, "vendor-id", 0); deviceid = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "device-id", 0); + DDI_PROP_DONTPASS, "device-id", 0); /* * first check for a match in the "pci-ide-blacklist" property */ rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, - "pci-ide-blacklist", &propp, &count); + "pci-ide-blacklist", &propp, &count); if (rc == DDI_PROP_SUCCESS) { count = (count * sizeof (uint_t)) / sizeof (pcibl_t); @@ -3053,12 +3091,12 @@ ata_check_pciide_blacklist( while (count--) { /* check for matching ID */ if ((vendorid & blp->b_vmask) - != (blp->b_vendorid & blp->b_vmask)) { + != (blp->b_vendorid & blp->b_vmask)) { blp++; continue; } if ((deviceid & blp->b_dmask) - != (blp->b_deviceid & blp->b_dmask)) { + != (blp->b_deviceid & blp->b_dmask)) { blp++; continue; } @@ -3099,7 +3137,7 @@ ata_check_drive_blacklist( for (blp = ata_drive_blacklist; blp->b_model; blp++) { if (!ata_strncmp(blp->b_model, aidp->ai_model, - sizeof (aidp->ai_model))) + sizeof (aidp->ai_model))) continue; if (blp->b_flags & flags) return (TRUE); @@ -3152,7 +3190,7 @@ ata_queue_cmd( * ap_start function is called. */ rc = ghd_transport(&ata_ctlp->ac_ccc, gcmdp, gcmdp->cmd_gtgtp, - 0, TRUE, NULL); + 0, TRUE, NULL); if (rc != TRAN_ACCEPT) { /* this should never, ever happen */ @@ -3230,7 +3268,7 @@ ata_check_revert_to_defaults( /* look for a disk-specific "revert" property" */ propval = ddi_getprop(DDI_DEV_T_ANY, ata_ctlp->ac_dip, - DDI_PROP_DONTPASS, prop_buf, -1); + DDI_PROP_DONTPASS, prop_buf, -1); if (propval == 0) return (FALSE); else if (propval != -1) @@ -3238,7 +3276,7 @@ ata_check_revert_to_defaults( /* look for a global "revert" property" */ propval = ddi_getprop(DDI_DEV_T_ANY, ata_ctlp->ac_dip, - 0, ATA_REVERT_PROP_GLOBAL, -1); + 0, ATA_REVERT_PROP_GLOBAL, -1); if (propval == 0) return (FALSE); else if (propval != -1) @@ -3262,7 +3300,7 @@ ata_show_transfer_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp) } ATAPRT(("?\tPIO mode %d selected\n", (ata_drvp->ad_id.ai_advpiomode & ATAC_ADVPIO_4_SUP) == - ATAC_ADVPIO_4_SUP ? 4 : 3)); + ATAC_ADVPIO_4_SUP ? 4 : 3)); } else { /* Using DMA */ if (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_SEL_MASK) { @@ -3271,10 +3309,10 @@ ata_show_transfer_mode(ata_ctl_t *ata_ctlp, ata_drv_t *ata_drvp) * selected, not both. */ ATAPRT(("?\tMultiwordDMA mode %d selected\n", - (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_2_SEL) == + (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_2_SEL) == ATAC_MDMA_2_SEL ? 2 : (ata_drvp->ad_id.ai_dworddma & ATAC_MDMA_1_SEL) == - ATAC_MDMA_1_SEL ? 1 : 0)); + ATAC_MDMA_1_SEL ? 1 : 0)); } else { for (i = 0; i <= 6; i++) { if (ata_drvp->ad_id.ai_ultradma & @@ -3330,9 +3368,9 @@ ata_spec_init_controller(dev_info_t *dip) struct ata_ctl_spec *ctlsp; vendor_id = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "vendor-id", 0); + DDI_PROP_DONTPASS, "vendor-id", 0); device_id = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "device-id", 0); + DDI_PROP_DONTPASS, "device-id", 0); /* Locate controller specific ops, if they exist */ ctlsp = ata_cntrls_spec; @@ -3375,7 +3413,7 @@ ata_prop_lookup_int(dev_t match_dev, dev_info_t *dip, int proprc; proprc = ddi_prop_lookup_string(match_dev, dip, - flags, name, &bufp); + flags, name, &bufp); if (proprc == DDI_PROP_SUCCESS) { cp = bufp; @@ -3390,3 +3428,287 @@ ata_prop_lookup_int(dev_t match_dev, dev_info_t *dip, return (rc); } + +/* + * Initialize the power management components + */ +static void +ata_init_pm(dev_info_t *dip) +{ + char pmc_name[16]; + char *pmc[] = { + NULL, + "0=Sleep (PCI D3 State)", + "3=PowerOn (PCI D0 State)", + NULL + }; + int instance; + ata_ctl_t *ata_ctlp; + + + instance = ddi_get_instance(dip); + ata_ctlp = ddi_get_soft_state(ata_state, instance); + ata_ctlp->ac_pm_support = 0; + + /* check PCI capabilities */ + if (!ata_is_pci(dip)) + return; + + (void) sprintf(pmc_name, "NAME=ata%d", instance); + pmc[0] = pmc_name; + +#ifdef ATA_USE_AUTOPM + if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip, + "pm-components", pmc, 3) != DDI_PROP_SUCCESS) { + return; + } +#endif + + ata_ctlp->ac_pm_support = 1; + ata_ctlp->ac_pm_level = PM_LEVEL_D0; + + ATA_BUSY_COMPONENT(dip, 0); + if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) { + (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "pm-components"); + } + ATA_IDLE_COMPONENT(dip, 0); +} + +/* + * resume the hard drive + */ +static void +ata_resume_drive(ata_drv_t *ata_drvp) +{ + ata_ctl_t *ata_ctlp = ata_drvp->ad_ctlp; + int drive_type; + struct ata_id id; + uint8_t udma; + + ADBG_TRACE(("ata_resume_drive entered\n")); + + drive_type = ata_drive_type(ata_drvp->ad_drive_bits, + ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1, + ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2, + &id); + if (drive_type == ATA_DEV_NONE) + return; + + /* Reset Ultra DMA mode */ + udma = ATACM_UDMA_SEL(&ata_drvp->ad_id); + if (udma != 0) { + uint8_t mode; + for (mode = 0; mode < 8; mode++) + if (((1 << mode) & udma) != 0) + break; + ASSERT(mode != 8); + + mode |= ATF_XFRMOD_UDMA; + + if (!ata_set_feature(ata_ctlp, ata_drvp, ATSF_SET_XFRMOD, mode)) + return; + } + + if (!ATAPIDRV(ata_drvp)) { + if (!ata_disk_setup_parms(ata_ctlp, ata_drvp)) + return; + (void) ata_set_feature(ata_ctlp, ata_drvp, ATSF_DIS_REVPOD, 0); + } +} + +/* + * resume routine, it will be run when get the command + * DDI_RESUME at attach(9E) from system power management + */ +static int +ata_resume(dev_info_t *dip) +{ + int instance; + ata_ctl_t *ata_ctlp; + ddi_acc_handle_t io_hdl2; + caddr_t ioaddr2; + + instance = ddi_get_instance(dip); + ata_ctlp = ddi_get_soft_state(ata_state, instance); + + if (!ata_ctlp->ac_pm_support) + return (DDI_FAILURE); + if (ata_ctlp->ac_pm_level == PM_LEVEL_D0) + return (DDI_SUCCESS); + + ATA_BUSY_COMPONENT(dip, 0); + if (ATA_RAISE_POWER(dip, 0, PM_LEVEL_D0) == DDI_FAILURE) + return (DDI_FAILURE); + ATA_IDLE_COMPONENT(dip, 0); + + /* enable interrupts from the device */ + io_hdl2 = ata_ctlp->ac_iohandle2; + ioaddr2 = ata_ctlp->ac_ioaddr2; + ddi_put8(io_hdl2, (uchar_t *)ioaddr2 + AT_DEVCTL, ATDC_D3); + ata_ctlp->ac_pm_level = PM_LEVEL_D0; + + return (DDI_SUCCESS); +} + +/* + * suspend routine, it will be run when get the command + * DDI_SUSPEND at detach(9E) from system power management + */ +static int +ata_suspend(dev_info_t *dip) +{ + int instance; + ata_ctl_t *ata_ctlp; + ddi_acc_handle_t io_hdl2; + + instance = ddi_get_instance(dip); + ata_ctlp = ddi_get_soft_state(ata_state, instance); + + if (!ata_ctlp->ac_pm_support) + return (DDI_FAILURE); + if (ata_ctlp->ac_pm_level == PM_LEVEL_D3) + return (DDI_SUCCESS); + + /* disable interrupts and turn the software reset bit on */ + io_hdl2 = ata_ctlp->ac_iohandle2; + ddi_put8(io_hdl2, ata_ctlp->ac_devctl, (ATDC_D3 | ATDC_SRST)); + + (void) ata_reset_bus(ata_ctlp); + (void) ata_change_power(dip, ATC_SLEEP); + ata_ctlp->ac_pm_level = PM_LEVEL_D3; + return (DDI_SUCCESS); +} + +int ata_save_pci_config = 0; +/* + * ata specific power management entry point, it was + * used to change the power management component + */ +static int +ata_power(dev_info_t *dip, int component, int level) +{ + int instance; + ata_ctl_t *ata_ctlp; + uint8_t cmd; + + ADBG_TRACE(("ata_power entered, component = %d, level = %d\n", + component, level)); + + instance = ddi_get_instance(dip); + ata_ctlp = ddi_get_soft_state(ata_state, instance); + if (ata_ctlp == NULL || component != 0) + return (DDI_FAILURE); + + if (!ata_ctlp->ac_pm_support) + return (DDI_FAILURE); + + switch (level) { + case PM_LEVEL_D0: + if (ata_save_pci_config) + (void) pci_restore_config_regs(dip); + ata_ctlp->ac_pm_level = PM_LEVEL_D0; + cmd = ATC_STANDBY_IM; + break; + case PM_LEVEL_D3: + if (ata_save_pci_config) + (void) pci_save_config_regs(dip); + ata_ctlp->ac_pm_level = PM_LEVEL_D3; + cmd = ATC_SLEEP; + break; + default: + return (DDI_FAILURE); + } + return (ata_change_power(dip, cmd)); +} + +/* + * sent commands to ata controller to change the power level + */ +static int +ata_change_power(dev_info_t *dip, uint8_t cmd) +{ + int instance; + ata_ctl_t *ata_ctlp; + ata_drv_t *ata_drvp; + uchar_t targ; + struct ata_id id; + uchar_t lun; + uchar_t lastlun; + + ADBG_TRACE(("ata_change_power entered, cmd = %d\n", cmd)); + + instance = ddi_get_instance(dip); + ata_ctlp = ddi_get_soft_state(ata_state, instance); + /* + * Issue command on each disk device on the bus. + */ + for (targ = 0; targ < ATA_MAXTARG; targ++) { + ata_drvp = CTL2DRV(ata_ctlp, targ, 0); + if (ata_drvp == NULL) + continue; + if (ata_drive_type(ata_drvp->ad_drive_bits, + ata_ctlp->ac_iohandle1, ata_ctlp->ac_ioaddr1, + ata_ctlp->ac_iohandle2, ata_ctlp->ac_ioaddr2, + &id) != ATA_DEV_DISK) + continue; + (void) ata_flush_cache(ata_ctlp, ata_drvp); + if (!ata_command(ata_ctlp, ata_drvp, TRUE, TRUE, 5 * 1000000, + cmd, 0, 0, 0, 0, 0, 0)) { + cmn_err(CE_WARN, "!ata_controller - Can not put " + "drive %d in to power mode %u", targ, cmd); + (void) ata_devo_reset(dip, DDI_RESET_FORCE); + return (DDI_FAILURE); + } + } + + if (cmd == ATC_SLEEP) + return (DDI_SUCCESS); + + for (targ = 0; targ < ATA_MAXTARG; targ++) { + ata_drvp = CTL2DRV(ata_ctlp, targ, 0); + if ((ata_drvp == NULL) || !(ata_drvp->ad_flags & AD_DISK)) + continue; + ata_resume_drive(ata_drvp); + + if (ATAPIDRV(ata_drvp)) + lastlun = ata_drvp->ad_id.ai_lastlun; + else + lastlun = 0; + if (!ata_enable_atapi_luns) + lastlun = 0; + for (lun = 1; lun <= lastlun && lun < ATA_MAXLUN; lun++) { + ata_drvp = CTL2DRV(ata_ctlp, targ, lun); + if (ata_drvp != NULL) + ata_resume_drive(ata_drvp); + } + (void) ata_software_reset(ata_ctlp); + } + + return (DDI_SUCCESS); +} + +/* + * return 1 when ata controller is a pci device, + * otherwise return 0 + */ +static int +ata_is_pci(dev_info_t *dip) +{ + int rc; + char *bufp; + int ispci; + + rc = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip), + DDI_PROP_DONTPASS, "device_type", &bufp); + + if (rc != DDI_PROP_SUCCESS) { + ADBG_ERROR(("ata_is_pci !device_type\n")); + return (0); + } + + ispci = (strcmp(bufp, "pci-ide") == 0); + + ddi_prop_free(bufp); + + return (ispci); +} 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 1df1252b55..22aef7c97e 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 @@ -177,6 +177,15 @@ extern "C" { * Feature register bits */ #define ATF_ATAPI_DMA 0x01 /* ATAPI DMA enable bit */ +#define ATF_XFRMOD_UDMA 0x40 /* Ultra DMA mode */ +#define ATACM_UDMA_SEL(id) (((id)->ai_ultradma >> 8) & 0x7f) + +/* + * Set feature register definitions. + */ +#define ATSF_SET_XFRMOD 0X03 /* Set transfer mode */ +#define ATSF_DIS_REVPOD 0x66 /* Disable reverting to power on defaults */ +#define ATSF_ENA_REVPOD 0xcc /* Enable reverting to power on defaults */ /* * common bits and options for set features (ATC_SET_FEAT) @@ -281,6 +290,12 @@ typedef struct ata_ctl { struct ata_pkt *ac_arq_pktp; /* pkt for performing ATAPI ARQ */ struct ata_pkt *ac_fault_pktp; /* pkt that caused ARQ */ uchar_t ac_arq_cdb[6]; + + /* + * Power Management + */ + int ac_pm_support; + int ac_pm_level; } ata_ctl_t; /* ac_flags (per-controller) */ diff --git a/usr/src/uts/intel/io/dktp/dcdev/dadk.c b/usr/src/uts/intel/io/dktp/dcdev/dadk.c index eaf5c28db0..5b99559cc3 100644 --- a/usr/src/uts/intel/io/dktp/dcdev/dadk.c +++ b/usr/src/uts/intel/io/dktp/dcdev/dadk.c @@ -73,6 +73,7 @@ static struct cmpkt *dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, static int dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), caddr_t arg); static void dadk_transport(opaque_t com_data, struct buf *bp); +static int dadk_ctl_ioctl(struct dadk *, uint32_t, uintptr_t, int); struct tgcom_objops dadk_com_ops = { nodev, @@ -336,6 +337,8 @@ dadk_init(opaque_t objp, opaque_t devp, opaque_t flcobjp, opaque_t queobjp, BBH_INIT(bbhobjp); dadkp->dad_flcobjp = flcobjp; + mutex_init(&dadkp->dad_cmd_mutex, NULL, MUTEX_DRIVER, NULL); + dadkp->dad_cmd_count = 0; return (FLC_INIT(flcobjp, &(dadkp->dad_com), queobjp, lkarg)); } @@ -364,6 +367,7 @@ dadk_cleanup(struct tgdk_obj *dkobjp) FLC_FREE(dadkp->dad_flcobjp); dadkp->dad_flcobjp = NULL; } + mutex_destroy(&dadkp->dad_cmd_mutex); } /* ARGSUSED */ @@ -376,7 +380,7 @@ dadk_probe(opaque_t objp, int kmsflg) devp = dadkp->dad_sd; if (!devp->sd_inq || (devp->sd_inq->inq_dtype == DTYPE_NOTPRESENT) || - (devp->sd_inq->inq_dtype == DTYPE_UNKNOWN)) { + (devp->sd_inq->inq_dtype == DTYPE_UNKNOWN)) { return (DDI_PROBE_FAILURE); } @@ -454,21 +458,23 @@ dadk_open(opaque_t objp, int flag) return (DDI_SUCCESS); } } else { - mutex_enter(&dadkp->dad_mutex); - dadkp->dad_iostate = DKIO_NONE; - cv_broadcast(&dadkp->dad_state_cv); - mutex_exit(&dadkp->dad_mutex); - - if (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 0, DADK_SILENT) || - dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT) || - dadk_rmb_ioctl(dadkp, DCMD_UPDATE_GEOM, 0, 0, DADK_SILENT)) { - return (DDI_FAILURE); - } - - mutex_enter(&dadkp->dad_mutex); - dadkp->dad_iostate = DKIO_INSERTED; - cv_broadcast(&dadkp->dad_state_cv); - mutex_exit(&dadkp->dad_mutex); + mutex_enter(&dadkp->dad_mutex); + dadkp->dad_iostate = DKIO_NONE; + cv_broadcast(&dadkp->dad_state_cv); + mutex_exit(&dadkp->dad_mutex); + + if (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 0, + DADK_SILENT) || + dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT) || + dadk_rmb_ioctl(dadkp, DCMD_UPDATE_GEOM, 0, 0, + DADK_SILENT)) { + return (DDI_FAILURE); + } + + mutex_enter(&dadkp->dad_mutex); + dadkp->dad_iostate = DKIO_INSERTED; + cv_broadcast(&dadkp->dad_state_cv); + mutex_exit(&dadkp->dad_mutex); } /* @@ -482,20 +488,20 @@ dadk_open(opaque_t objp, int flag) * is added to the driver to change WCE, dad_wce * must be updated appropriately. */ - error = CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETWCE, + error = dadk_ctl_ioctl(dadkp, DIOCTL_GETWCE, (uintptr_t)&wce, FKIOCTL | FNATIVE); mutex_enter(&dadkp->dad_mutex); dadkp->dad_wce = (error != 0) || (wce != 0); mutex_exit(&dadkp->dad_mutex); /* logical disk geometry */ - CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETGEOM, + (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETGEOM, (uintptr_t)&dadkp->dad_logg, FKIOCTL | FNATIVE); if (dadkp->dad_logg.g_cap == 0) return (DDI_FAILURE); /* get physical disk geometry */ - CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETPHYGEOM, + (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETPHYGEOM, (uintptr_t)&dadkp->dad_phyg, FKIOCTL | FNATIVE); if (dadkp->dad_phyg.g_cap == 0) return (DDI_FAILURE); @@ -507,7 +513,7 @@ dadk_open(opaque_t objp, int flag) /* start profiling */ FLC_START_KSTAT(dadkp->dad_flcobjp, "disk", - ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); + ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); return (DDI_SUCCESS); } @@ -534,7 +540,8 @@ dadk_setcap(struct dadk *dadkp) /* set sec,block shift factor - (512->0, 1024->1, 2048->2, etc.) */ totsize >>= SCTRSHFT; - for (i = 0; totsize != 1; i++, totsize >>= 1); + for (i = 0; totsize != 1; i++, totsize >>= 1) + ; dadkp->dad_blkshf = i; dadkp->dad_secshf = i + SCTRSHFT; } @@ -594,14 +601,14 @@ dadk_create_errstats(struct dadk *dadkp, int instance) dep->dadk_model.value.c[0] = 0; dadk_ioc_string.is_buf = &dep->dadk_model.value.c[0]; dadk_ioc_string.is_size = sizeof (dep->dadk_model.value.c); - CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETMODEL, + (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETMODEL, (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE); /* get serial */ dep->dadk_serial.value.c[0] = 0; dadk_ioc_string.is_buf = &dep->dadk_serial.value.c[0]; dadk_ioc_string.is_size = sizeof (dep->dadk_serial.value.c); - CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETSERIAL, + (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETSERIAL, (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE); /* Get revision */ @@ -659,6 +666,9 @@ dadk_strategy(opaque_t objp, struct buf *bp) } SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf))); + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count++; + mutex_exit(&dadkp->dad_cmd_mutex); FLC_ENQUE(dadkp->dad_flcobjp, bp); return (DDI_SUCCESS); @@ -715,7 +725,7 @@ dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, switch (cmd) { case DKIOCGETDEF: - { + { struct buf *bp; int err, head; unsigned char *secbuf; @@ -752,6 +762,9 @@ dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, bp->b_forw = (struct buf *)dadkp; bp->b_back = (struct buf *)DCMD_GETDEF; + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count++; + mutex_exit(&dadkp->dad_cmd_mutex); FLC_ENQUE(dadkp->dad_flcobjp, bp); err = biowait(bp); if (!err) { @@ -762,9 +775,9 @@ dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, kmem_free(secbuf, NBPSCTR); freerbuf(bp); return (err); - } + } case DIOCTL_RWCMD: - { + { struct dadkio_rwcmd *rwcmdp; int status, rw; @@ -794,8 +807,8 @@ dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, return (status); default: return (EINVAL); + } } - } case DKIOC_UPDATEFW: /* @@ -805,7 +818,7 @@ dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, if (PRIV_POLICY(cred_p, PRIV_ALL, B_FALSE, EPERM, NULL) != 0) return (EPERM); else - return (CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag)); + return (dadk_ctl_ioctl(dadkp, cmd, arg, flag)); case DKIOCFLUSHWRITECACHE: { @@ -884,6 +897,9 @@ dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, CTL_IOSETUP(dadkp->dad_ctlobjp, pktp); + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count++; + mutex_exit(&dadkp->dad_cmd_mutex); FLC_ENQUE(dadkp->dad_flcobjp, bp); if (is_sync) { @@ -894,16 +910,16 @@ dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, } default: if (!dadkp->dad_rmb) - return (CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag)); + return (dadk_ctl_ioctl(dadkp, cmd, arg, flag)); } switch (cmd) { case CDROMSTOP: return (dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, - 0, DADK_SILENT)); + 0, DADK_SILENT)); case CDROMSTART: return (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, - 0, DADK_SILENT)); + 0, DADK_SILENT)); case DKIOCLOCK: return (dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT)); case DKIOCUNLOCK: @@ -914,11 +930,11 @@ dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, int ret; if (ret = dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, - DADK_SILENT)) { + DADK_SILENT)) { return (ret); } if (ret = dadk_rmb_ioctl(dadkp, DCMD_EJECT, 0, 0, - DADK_SILENT)) { + DADK_SILENT)) { return (ret); } mutex_enter(&dadkp->dad_mutex); @@ -1036,7 +1052,7 @@ dadk_iob_alloc(opaque_t objp, daddr_t blkno, ssize_t xfer, int kmsflg) iobp->b_psec = LBLK2SEC(blkno, dadkp->dad_blkshf); iobp->b_pbyteoff = (blkno & ((1<<dadkp->dad_blkshf) - 1)) << SCTRSHFT; iobp->b_pbytecnt = ((iobp->b_pbyteoff + xfer + dadkp->DAD_SECSIZ - 1) - >> dadkp->dad_secshf) << dadkp->dad_secshf; + >> dadkp->dad_secshf) << dadkp->dad_secshf; bp->b_un.b_addr = 0; /* @@ -1107,6 +1123,9 @@ dadk_iob_xfer(opaque_t objp, struct tgdk_iob *iobp, int rw) bp->b_resid = 0; /* call flow control */ + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count++; + mutex_exit(&dadkp->dad_cmd_mutex); FLC_ENQUE(dadkp->dad_flcobjp, bp); err = biowait(bp); @@ -1253,16 +1272,15 @@ dadk_ioretry(struct cmpkt *pktp, int action) if (pktp->cp_retry++ < DADK_RETRY_COUNT) { CTL_IOSETUP(dadkp->dad_ctlobjp, pktp); if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == - CTL_SEND_SUCCESS) { + CTL_SEND_SUCCESS) { return (JUST_RETURN); } gda_log(dadkp->dad_sd->sd_dev, dadk_name, - CE_WARN, - "transport of command fails\n"); + CE_WARN, "transport of command fails\n"); } else gda_log(dadkp->dad_sd->sd_dev, - dadk_name, CE_WARN, - "exceeds maximum number of retries\n"); + dadk_name, CE_WARN, + "exceeds maximum number of retries\n"); bioerror(pktp->cp_bp, ENXIO); /*FALLTHROUGH*/ case COMMAND_DONE_ERROR: @@ -1378,7 +1396,7 @@ dadk_chkerr(struct cmpkt *pktp) if (pktp->cp_retry) { err_blkno = pktp->cp_srtsec + ((pktp->cp_bytexfer - - pktp->cp_resid) >> dadkp->dad_secshf); + pktp->cp_resid) >> dadkp->dad_secshf); } else err_blkno = -1; @@ -1468,11 +1486,10 @@ dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp) rwcmdp->status.failed_blk = rwcmdp->blkaddr + - ((pktp->cp_bytexfer - - pktp->cp_resid) >> dadkp->dad_secshf); + ((pktp->cp_bytexfer - pktp->cp_resid) >> dadkp->dad_secshf); rwcmdp->status.resid = pktp->cp_bp->b_resid + - pktp->cp_byteleft - pktp->cp_bytexfer + pktp->cp_resid; + pktp->cp_byteleft - pktp->cp_bytexfer + pktp->cp_resid; switch ((int)(* (char *)pktp->cp_scbp)) { case DERR_AMNF: case DERR_ABORT: @@ -1504,14 +1521,22 @@ dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp) if (rwcmdp->flags & DADKIO_FLAG_SILENT) return; gda_errmsg(dadkp->dad_sd, pktp, dadk_name, dadk_errtab[scb].d_severity, - rwcmdp->blkaddr, rwcmdp->status.failed_blk, - dadk_cmds, dadk_sense); + rwcmdp->blkaddr, rwcmdp->status.failed_blk, + dadk_cmds, dadk_sense); } /*ARGSUSED*/ static void dadk_polldone(struct buf *bp) { + struct cmpkt *pktp; + struct dadk *dadkp; + + pktp = GDA_BP_PKT(bp); + dadkp = PKT2DADK(pktp); + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count--; + mutex_exit(&dadkp->dad_cmd_mutex); } static void @@ -1544,6 +1569,9 @@ dadk_iodone(struct buf *bp) if (pktp->cp_private) BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private); gda_free(dadkp->dad_ctlobjp, pktp, NULL); + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count--; + mutex_exit(&dadkp->dad_cmd_mutex); biodone(bp); } @@ -1558,7 +1586,7 @@ dadk_check_media(opaque_t objp, int *state) #ifdef DADK_DEBUG if (dadk_debug & DSTATE) PRF("dadk_check_media: user state %x disk state %x\n", - *state, dadkp->dad_iostate); + *state, dadkp->dad_iostate); #endif /* * If state already changed just return @@ -1676,7 +1704,7 @@ dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, int silent) bp->b_forw = (struct buf *)dadkp->dad_flcobjp; pktp->cp_passthru = (opaque_t)(intptr_t)silent; - err = CTL_IOCTL(dadkp->dad_ctlobjp, cmd, (uintptr_t)pktp, flags); + err = dadk_ctl_ioctl(dadkp, cmd, (uintptr_t)pktp, flags); freerbuf(bp); gda_free(dadkp->dad_ctlobjp, pktp, NULL); return (err); @@ -1698,6 +1726,9 @@ dadk_rmb_iodone(struct buf *bp) /* Start next one */ FLC_DEQUE(dadkp->dad_flcobjp, bp); + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count--; + mutex_exit(&dadkp->dad_cmd_mutex); biodone(bp); } @@ -1769,5 +1800,42 @@ dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *rwcmdp, struct buf *bp) (void) dadk_ioprep(dadkp, pktp); + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count++; + mutex_exit(&dadkp->dad_cmd_mutex); FLC_ENQUE(dadkp->dad_flcobjp, bp); } + +/* + * There is no existing way to notify cmdk module + * when the command completed, so add this function + * to calculate how many on-going commands. + */ +int +dadk_getcmds(opaque_t objp) +{ + struct dadk *dadkp = (struct dadk *)objp; + int count; + + mutex_enter(&dadkp->dad_cmd_mutex); + count = dadkp->dad_cmd_count; + mutex_exit(&dadkp->dad_cmd_mutex); + return (count); +} + +/* + * this function was used to calc the cmd for CTL_IOCTL + */ +static int +dadk_ctl_ioctl(struct dadk *dadkp, uint32_t cmd, uintptr_t arg, int flag) +{ + int error; + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count++; + mutex_exit(&dadkp->dad_cmd_mutex); + error = CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag); + mutex_enter(&dadkp->dad_cmd_mutex); + dadkp->dad_cmd_count--; + mutex_exit(&dadkp->dad_cmd_mutex); + return (error); +} diff --git a/usr/src/uts/intel/io/dktp/disk/cmdk.c b/usr/src/uts/intel/io/dktp/disk/cmdk.c index 4ce5a60250..d14946bcf2 100644 --- a/usr/src/uts/intel/io/dktp/disk/cmdk.c +++ b/usr/src/uts/intel/io/dktp/disk/cmdk.c @@ -163,6 +163,11 @@ static int cmdkprobe(dev_info_t *dip); static int cmdkattach(dev_info_t *dip, ddi_attach_cmd_t cmd); static int cmdkdetach(dev_info_t *dip, ddi_detach_cmd_t cmd); +static void cmdk_setup_pm(dev_info_t *dip, struct cmdk *dkp); +static int cmdkresume(dev_info_t *dip); +static int cmdksuspend(dev_info_t *dip); +static int cmdkpower(dev_info_t *dip, int component, int level); + struct dev_ops cmdk_ops = { DEVO_REV, /* devo_rev, */ 0, /* refcnt */ @@ -173,7 +178,8 @@ struct dev_ops cmdk_ops = { cmdkdetach, /* detach */ nodev, /* reset */ &cmdk_cb_ops, /* driver operations */ - (struct bus_ops *)0 /* bus operations */ + (struct bus_ops *)0, /* bus operations */ + cmdkpower /* power */ }; /* @@ -322,13 +328,22 @@ cmdkattach(dev_info_t *dip, ddi_attach_cmd_t cmd) struct cmdk *dkp; char *node_type; - if (cmd != DDI_ATTACH) + switch (cmd) { + case DDI_ATTACH: + break; + case DDI_RESUME: + return (cmdkresume(dip)); + default: return (DDI_FAILURE); + } instance = ddi_get_instance(dip); if (!(dkp = ddi_get_soft_state(cmdk_state, instance))) return (DDI_FAILURE); + dkp->dk_pm_level = CMDK_SPINDLE_UNINIT; + mutex_init(&dkp->dk_mutex, NULL, MUTEX_DRIVER, NULL); + mutex_enter(&dkp->dk_mutex); /* dadk_attach is an empty function that only returns SUCCESS */ @@ -386,6 +401,13 @@ cmdkattach(dev_info_t *dip, ddi_attach_cmd_t cmd) DDI_KERNEL_IOCTL, NULL, 0); ddi_report_dev(dip); + /* + * Initialize power management + */ + mutex_init(&dkp->dk_pm_mutex, NULL, MUTEX_DRIVER, NULL); + cv_init(&dkp->dk_suspend_cv, NULL, CV_DRIVER, NULL); + cmdk_setup_pm(dip, dkp); + return (DDI_SUCCESS); fail1: @@ -408,7 +430,13 @@ cmdkdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) int instance; int max_instance; - if (cmd != DDI_DETACH) { + switch (cmd) { + case DDI_DETACH: + /* return (DDI_FAILURE); */ + break; + case DDI_SUSPEND: + return (cmdksuspend(dip)); + default: #ifdef CMDK_DEBUG if (cmdk_debug & DIO) { PRF("cmdkdetach: cmd = %d unknown\n", cmd); @@ -454,6 +482,8 @@ cmdkdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) mutex_exit(&dkp->dk_mutex); mutex_destroy(&dkp->dk_mutex); rw_destroy(&dkp->dk_bbh_mutex); + mutex_destroy(&dkp->dk_pm_mutex); + cv_destroy(&dkp->dk_suspend_cv); ddi_soft_state_free(cmdk_state, instance); return (DDI_SUCCESS); @@ -490,6 +520,145 @@ cmdkinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) return (DDI_SUCCESS); } +/* + * Initialize the power management components + */ +static void +cmdk_setup_pm(dev_info_t *dip, struct cmdk *dkp) +{ + char *pm_comp[] = { "NAME=cmdk", "0=off", "1=on", NULL }; + + /* + * Since the cmdk device does not the 'reg' property, + * cpr will not call its DDI_SUSPEND/DDI_RESUME entries. + * The following code is to tell cpr that this device + * DOES need to be suspended and resumed. + */ + (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, + "pm-hardware-state", "needs-suspend-resume"); + + if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip, + "pm-components", pm_comp, 3) == DDI_PROP_SUCCESS) { + if (pm_raise_power(dip, 0, CMDK_SPINDLE_ON) == DDI_SUCCESS) { + mutex_enter(&dkp->dk_pm_mutex); + dkp->dk_pm_level = CMDK_SPINDLE_ON; + dkp->dk_pm_is_enabled = 1; + mutex_exit(&dkp->dk_pm_mutex); + } else { + mutex_enter(&dkp->dk_pm_mutex); + dkp->dk_pm_level = CMDK_SPINDLE_OFF; + dkp->dk_pm_is_enabled = 0; + mutex_exit(&dkp->dk_pm_mutex); + } + } else { + mutex_enter(&dkp->dk_pm_mutex); + dkp->dk_pm_level = CMDK_SPINDLE_UNINIT; + dkp->dk_pm_is_enabled = 0; + mutex_exit(&dkp->dk_pm_mutex); + } +} + +/* + * suspend routine, it will be run when get the command + * DDI_SUSPEND at detach(9E) from system power management + */ +static int +cmdksuspend(dev_info_t *dip) +{ + struct cmdk *dkp; + int instance; + clock_t count = 0; + + instance = ddi_get_instance(dip); + if (!(dkp = ddi_get_soft_state(cmdk_state, instance))) + return (DDI_FAILURE); + mutex_enter(&dkp->dk_mutex); + if (dkp->dk_flag & CMDK_SUSPEND) { + mutex_exit(&dkp->dk_mutex); + return (DDI_SUCCESS); + } + dkp->dk_flag |= CMDK_SUSPEND; + + /* need to wait a while */ + while (dadk_getcmds(DKTP_DATA) != 0) { + delay(drv_usectohz(1000000)); + if (count > 60) { + dkp->dk_flag &= ~CMDK_SUSPEND; + cv_broadcast(&dkp->dk_suspend_cv); + mutex_exit(&dkp->dk_mutex); + return (DDI_FAILURE); + } + count++; + } + mutex_exit(&dkp->dk_mutex); + return (DDI_SUCCESS); +} + +/* + * resume routine, it will be run when get the command + * DDI_RESUME at attach(9E) from system power management + */ +static int +cmdkresume(dev_info_t *dip) +{ + struct cmdk *dkp; + int instance; + + instance = ddi_get_instance(dip); + if (!(dkp = ddi_get_soft_state(cmdk_state, instance))) + return (DDI_FAILURE); + mutex_enter(&dkp->dk_mutex); + if (!(dkp->dk_flag & CMDK_SUSPEND)) { + mutex_exit(&dkp->dk_mutex); + return (DDI_FAILURE); + } + dkp->dk_pm_level = CMDK_SPINDLE_ON; + dkp->dk_flag &= ~CMDK_SUSPEND; + cv_broadcast(&dkp->dk_suspend_cv); + mutex_exit(&dkp->dk_mutex); + return (DDI_SUCCESS); + +} + +/* + * power management entry point, it was used to + * change power management component. + * Actually, the real hard drive suspend/resume + * was handled in ata, so this function is not + * doing any real work other than verifying that + * the disk is idle. + */ +static int +cmdkpower(dev_info_t *dip, int component, int level) +{ + struct cmdk *dkp; + int instance; + + instance = ddi_get_instance(dip); + if (!(dkp = ddi_get_soft_state(cmdk_state, instance)) || + component != 0 || level > CMDK_SPINDLE_ON || + level < CMDK_SPINDLE_OFF) { + return (DDI_FAILURE); + } + + mutex_enter(&dkp->dk_pm_mutex); + if (dkp->dk_pm_is_enabled && dkp->dk_pm_level == level) { + mutex_exit(&dkp->dk_pm_mutex); + return (DDI_SUCCESS); + } + mutex_exit(&dkp->dk_pm_mutex); + + if ((level == CMDK_SPINDLE_OFF) && + (dadk_getcmds(DKTP_DATA) != 0)) { + return (DDI_FAILURE); + } + + mutex_enter(&dkp->dk_pm_mutex); + dkp->dk_pm_level = level; + mutex_exit(&dkp->dk_pm_mutex); + return (DDI_SUCCESS); +} + static int cmdk_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, char *name, caddr_t valuep, int *lengthp) @@ -677,6 +846,12 @@ cmdkioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp) if (!(dkp = ddi_get_soft_state(cmdk_state, instance))) return (ENXIO); + mutex_enter(&dkp->dk_mutex); + while (dkp->dk_flag & CMDK_SUSPEND) { + cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex); + } + mutex_exit(&dkp->dk_mutex); + bzero(data, sizeof (data)); switch (cmd) { @@ -873,6 +1048,10 @@ cmdkclose(dev_t dev, int flag, int otyp, cred_t *credp) return (ENXIO); } + while (dkp->dk_flag & CMDK_SUSPEND) { + cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex); + } + part = CMDKPART(dev); partbit = 1 << part; @@ -926,6 +1105,12 @@ cmdkopen(dev_t *dev_p, int flag, int otyp, cred_t *credp) if (otyp >= OTYPCNT) return (EINVAL); + mutex_enter(&dkp->dk_mutex); + while (dkp->dk_flag & CMDK_SUSPEND) { + cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex); + } + mutex_exit(&dkp->dk_mutex); + part = CMDKPART(dev); partbit = 1 << part; nodelay = (flag & (FNDELAY | FNONBLOCK)); @@ -1040,12 +1225,38 @@ cmdkmin(struct buf *bp) static int cmdkrw(dev_t dev, struct uio *uio, int flag) { + int instance; + struct cmdk *dkp; + + instance = CMDKUNIT(dev); + if (!(dkp = ddi_get_soft_state(cmdk_state, instance))) + return (ENXIO); + + mutex_enter(&dkp->dk_mutex); + while (dkp->dk_flag & CMDK_SUSPEND) { + cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex); + } + mutex_exit(&dkp->dk_mutex); + return (physio(cmdkstrategy, (struct buf *)0, dev, flag, cmdkmin, uio)); } static int cmdkarw(dev_t dev, struct aio_req *aio, int flag) { + int instance; + struct cmdk *dkp; + + instance = CMDKUNIT(dev); + if (!(dkp = ddi_get_soft_state(cmdk_state, instance))) + return (ENXIO); + + mutex_enter(&dkp->dk_mutex); + while (dkp->dk_flag & CMDK_SUSPEND) { + cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex); + } + mutex_exit(&dkp->dk_mutex); + return (aphysio(cmdkstrategy, anocancel, dev, flag, cmdkmin, aio)); } @@ -1070,6 +1281,12 @@ cmdkstrategy(struct buf *bp) return (0); } + mutex_enter(&dkp->dk_mutex); + while (dkp->dk_flag & CMDK_SUSPEND) { + cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex); + } + mutex_exit(&dkp->dk_mutex); + bp->b_flags &= ~(B_DONE|B_ERROR); bp->b_resid = 0; bp->av_back = NULL; @@ -1895,7 +2112,7 @@ cmdk_bbh_gethandle(opaque_t bbh_data, struct buf *bp) /* at least one bad sector in our section. break it. */ /* CASE 5: */ if ((lastsec >= altp->bad_start) && - (lastsec <= altp->bad_end)) { + (lastsec <= altp->bad_end)) { ckp[idx+1].ck_seclen = lastsec - altp->bad_start + 1; ckp[idx].ck_seclen -= ckp[idx+1].ck_seclen; ckp[idx+1].ck_sector = altp->good_start; diff --git a/usr/src/uts/intel/io/dktp/hba/ghd/ghd_debug.c b/usr/src/uts/intel/io/dktp/hba/ghd/ghd_debug.c index 068dbd9f76..ae591ae1b8 100644 --- a/usr/src/uts/intel/io/dktp/hba/ghd/ghd_debug.c +++ b/usr/src/uts/intel/io/dktp/hba/ghd/ghd_debug.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -56,28 +56,29 @@ ghd_err(const char *fmt, ...) } #if defined(GHD_DEBUG) +#include <sys/promif.h> #define PRF prom_printf static void ghd_dump_ccc(ccc_t *P) { PRF("nextp 0x%p tmrp 0x%p label 0x%p &mutex 0x%p\n", - P->ccc_nextp, P->ccc_tmrp, P->ccc_label, &P->ccc_activel_mutex); + P->ccc_nextp, P->ccc_tmrp, P->ccc_label, &P->ccc_activel_mutex); PRF("&activel 0x%p dip 0x%p iblock 0x%p\n", - &P->ccc_activel, P->ccc_hba_dip, P->ccc_iblock); + &P->ccc_activel, P->ccc_hba_dip, P->ccc_iblock); PRF("softid 0x%p &hba_mutext 0x%p\n poll 0x%p\n", - P->ccc_soft_id, &P->ccc_hba_mutex, &P->ccc_hba_pollmode); + P->ccc_soft_id, &P->ccc_hba_mutex, &P->ccc_hba_pollmode); PRF("&devs 0x%p &waitq_mutex 0x%p &waitq 0x%p\n", - &P->ccc_devs, &P->ccc_waitq_mutex, &P->ccc_waitq); + &P->ccc_devs, &P->ccc_waitq_mutex, &P->ccc_waitq); PRF("waitq_freezetime 0x%p waitq_freezedelay %p\n", - &P->ccc_waitq_freezetime, &P->ccc_waitq_freezedelay); + &P->ccc_waitq_freezetime, &P->ccc_waitq_freezedelay); PRF("dq softid 0x%p &dq_mutex 0x%p &doneq 0x%p\n", - P->ccc_doneq_softid, &P->ccc_doneq_mutex, &P->ccc_doneq); + P->ccc_doneq_softid, &P->ccc_doneq_mutex, &P->ccc_doneq); PRF("handle 0x%p &ccballoc 0x%p\n", - P->ccc_hba_handle, &P->ccc_ccballoc); + P->ccc_hba_handle, &P->ccc_ccballoc); PRF("hba_reset_notify_callback 0x%p notify_list 0x%p mutex 0x%p\n", - P->ccc_hba_reset_notify_callback, &P->ccc_reset_notify_list, - &P->ccc_reset_notify_mutex); + P->ccc_hba_reset_notify_callback, &P->ccc_reset_notify_list, + &P->ccc_reset_notify_mutex); } diff --git a/usr/src/uts/intel/io/pci/pci_pci.c b/usr/src/uts/intel/io/pci/pci_pci.c index b6dbe7f1b9..753c04d8f8 100644 --- a/usr/src/uts/intel/io/pci/pci_pci.c +++ b/usr/src/uts/intel/io/pci/pci_pci.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -319,7 +319,7 @@ ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) DDI_FM_EREPORT_CAPABLE)) pci_ereport_setup(devi); if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE) - ddi_fm_handler_register(devi, ppb_fm_callback, NULL); + ddi_fm_handler_register(devi, ppb_fm_callback, NULL); if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) { if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE) @@ -348,7 +348,8 @@ ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) * to this bus. */ if (pcihp_init(devi) != DDI_SUCCESS) - cmn_err(CE_WARN, "pci: Failed to setup hotplug framework"); + cmn_err(CE_WARN, + "pci: Failed to setup hotplug framework"); ddi_report_dev(devi); return (DDI_SUCCESS); @@ -419,7 +420,7 @@ ppb_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, pdip = (dev_info_t *)DEVI(dip)->devi_parent; return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip, - rdip, mp, offset, len, vaddrp)); + rdip, mp, offset, len, vaddrp)); } /*ARGSUSED*/ @@ -432,6 +433,7 @@ ppb_ctlops(dev_info_t *dip, dev_info_t *rdip, int rn; int totreg; ppb_devstate_t *ppb; + struct attachspec *asp; switch (ctlop) { case DDI_CTLOPS_REPORTDEV: @@ -459,6 +461,22 @@ ppb_ctlops(dev_info_t *dip, dev_info_t *rdip, return (DDI_FAILURE); break; + /* X86 systems support PME wakeup from suspend */ + case DDI_CTLOPS_ATTACH: + asp = (struct attachspec *)arg; + if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE) + if (pci_pre_resume(rdip) != DDI_SUCCESS) + return (DDI_FAILURE); + return (ddi_ctlops(dip, rdip, ctlop, arg, result)); + + + case DDI_CTLOPS_DETACH: + asp = (struct attachspec *)arg; + if (asp->cmd == DDI_SUSPEND && asp->when == DDI_POST) + if (pci_post_suspend(rdip) != DDI_SUCCESS) + return (DDI_FAILURE); + return (ddi_ctlops(dip, rdip, ctlop, arg, result)); + case DDI_CTLOPS_PEEK: case DDI_CTLOPS_POKE: ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(dip)); @@ -474,8 +492,8 @@ ppb_ctlops(dev_info_t *dip, dev_info_t *rdip, *(int *)result = 0; if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, - DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg", - (caddr_t)&drv_regp, ®len) != DDI_SUCCESS) + DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg", + (caddr_t)&drv_regp, ®len) != DDI_SUCCESS) return (DDI_FAILURE); totreg = reglen / sizeof (pci_regspec_t); @@ -596,8 +614,8 @@ ppb_initchild(dev_info_t *child) } /* transfer select properties from PROM to kernel */ - if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "interrupts", - -1) != -1) { + if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, + "interrupts", -1) != -1) { pdptr = kmem_zalloc((sizeof (struct ddi_parent_private_data) + sizeof (struct intrspec)), KM_SLEEP); pdptr->par_intr = (struct intrspec *)(pdptr + 1); @@ -660,20 +678,20 @@ ppb_save_config_regs(ppb_devstate_t *ppb_p) ddi_acc_handle_t config_handle; for (i = 0, dip = ddi_get_child(ppb_p->dip); dip != NULL; - i++, dip = ddi_get_next_sibling(dip)) { + i++, dip = ddi_get_next_sibling(dip)) { if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) { cmn_err(CE_WARN, "%s%d: can't config space for %s%d\n", - ddi_driver_name(ppb_p->dip), - ddi_get_instance(ppb_p->dip), - ddi_driver_name(dip), - ddi_get_instance(dip)); + ddi_driver_name(ppb_p->dip), + ddi_get_instance(ppb_p->dip), + ddi_driver_name(dip), + ddi_get_instance(dip)); continue; } ppb_p->config_state[i].dip = dip; ppb_p->config_state[i].command = - pci_config_get16(config_handle, PCI_CONF_COMM); + pci_config_get16(config_handle, PCI_CONF_COMM); pci_config_teardown(&config_handle); } ppb_p->config_state_index = i; @@ -701,14 +719,14 @@ ppb_restore_config_regs(ppb_devstate_t *ppb_p) dip = ppb_p->config_state[i].dip; if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) { cmn_err(CE_WARN, "%s%d: can't config space for %s%d\n", - ddi_driver_name(ppb_p->dip), - ddi_get_instance(ppb_p->dip), - ddi_driver_name(dip), - ddi_get_instance(dip)); + ddi_driver_name(ppb_p->dip), + ddi_get_instance(ppb_p->dip), + ddi_driver_name(dip), + ddi_get_instance(dip)); continue; } pci_config_put16(config_handle, PCI_CONF_COMM, - ppb_p->config_state[i].command); + ppb_p->config_state[i].command); pci_config_teardown(&config_handle); } } diff --git a/usr/src/uts/intel/io/vgatext/vgatext.c b/usr/src/uts/intel/io/vgatext/vgatext.c index 7835b63ecd..4e85cd7fd9 100644 --- a/usr/src/uts/intel/io/vgatext/vgatext.c +++ b/usr/src/uts/intel/io/vgatext/vgatext.c @@ -86,6 +86,15 @@ #define VGA_MMAP_FB_BASE VGA_MEM_ADDR +/* + * This variable allows for this driver to suspend even if it + * shouldn't. Note that by setting it, the framebuffer will probably + * not come back. So use it with a serial console, or with serial + * line debugging (say, for example, if this driver is being modified + * to support _some_ hardware doing suspend and resume). + */ +int vgatext_force_suspend = 0; + static int vgatext_open(dev_t *, int, int, cred_t *); static int vgatext_close(dev_t, int, int, cred_t *); static int vgatext_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); @@ -271,7 +280,7 @@ _init(void) e = mod_install(&modlinkage); if (e) { - ddi_soft_state_fini(&vgatext_softc_head); + ddi_soft_state_fini(&vgatext_softc_head); } return (e); } @@ -282,7 +291,7 @@ _fini(void) int e; if ((e = mod_remove(&modlinkage)) != 0) - return (e); + return (e); ddi_soft_state_fini(&vgatext_softc_head); @@ -334,7 +343,7 @@ vgatext_check_for_console(dev_info_t *devi, struct vgatext_softc *softc, if (pci_config_setup(devi, &pci_conf) != DDI_SUCCESS) { cmn_err(CE_WARN, - MYNAME ": can't get PCI conf handle"); + MYNAME ": can't get PCI conf handle"); return; } @@ -410,12 +419,18 @@ vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) switch (cmd) { case DDI_ATTACH: - break; + break; case DDI_RESUME: - return (DDI_SUCCESS); + /* + * Though vgatext doesn't really know how to resume + * on a generic framebuffer, we should succeed, as + * it is far better to have no console, than potentiall + * have no machine. + */ + return (DDI_SUCCESS); default: - return (DDI_FAILURE); + return (DDI_FAILURE); } /* DDI_ATTACH */ @@ -436,7 +451,7 @@ vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) softc->polledio.cursor = vgatext_polled_cursor; error = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(devi), - DDI_PROP_DONTPASS, "device_type", &parent_type); + DDI_PROP_DONTPASS, "device_type", &parent_type); if (error != DDI_SUCCESS) { cmn_err(CE_WARN, MYNAME ": can't determine parent type."); goto fail; @@ -444,47 +459,47 @@ vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) if (STREQ(parent_type, "isa") || STREQ(parent_type, "eisa")) { reg_rnumber = vgatext_get_isa_reg_index(devi, 1, VGA_REG_ADDR, - ®_offset); + ®_offset); if (reg_rnumber < 0) { cmn_err(CE_WARN, - MYNAME ": can't find reg entry for registers"); + MYNAME ": can't find reg entry for registers"); error = DDI_FAILURE; goto fail; } softc->fb_regno = vgatext_get_isa_reg_index(devi, 0, - VGA_MEM_ADDR, &mem_offset); + VGA_MEM_ADDR, &mem_offset); if (softc->fb_regno < 0) { cmn_err(CE_WARN, - MYNAME ": can't find reg entry for memory"); + MYNAME ": can't find reg entry for memory"); error = DDI_FAILURE; goto fail; } } else if (STREQ(parent_type, "pci") || STREQ(parent_type, "pciex")) { pci_pcie_bus = 1; reg_rnumber = vgatext_get_pci_reg_index(devi, - PCI_REG_ADDR_M|PCI_REG_REL_M, - PCI_ADDR_IO|PCI_RELOCAT_B, VGA_REG_ADDR, - ®_offset); + PCI_REG_ADDR_M|PCI_REG_REL_M, + PCI_ADDR_IO|PCI_RELOCAT_B, VGA_REG_ADDR, + ®_offset); if (reg_rnumber < 0) { cmn_err(CE_WARN, - MYNAME ": can't find reg entry for registers"); + MYNAME ": can't find reg entry for registers"); error = DDI_FAILURE; goto fail; } softc->fb_regno = vgatext_get_pci_reg_index(devi, - PCI_REG_ADDR_M|PCI_REG_REL_M, - PCI_ADDR_MEM32|PCI_RELOCAT_B, VGA_MEM_ADDR, - &mem_offset); + PCI_REG_ADDR_M|PCI_REG_REL_M, + PCI_ADDR_MEM32|PCI_RELOCAT_B, VGA_MEM_ADDR, + &mem_offset); if (softc->fb_regno < 0) { cmn_err(CE_WARN, - MYNAME ": can't find reg entry for memory"); + MYNAME ": can't find reg entry for memory"); error = DDI_FAILURE; goto fail; } agpm = 1; /* should have AGP master support */ } else { cmn_err(CE_WARN, MYNAME ": unknown parent type \"%s\".", - parent_type); + parent_type); error = DDI_FAILURE; goto fail; } @@ -492,8 +507,8 @@ vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) parent_type = NULL; error = ddi_regs_map_setup(devi, reg_rnumber, - (caddr_t *)&softc->regs.addr, reg_offset, VGA_REG_SIZE, - &dev_attr, &softc->regs.handle); + (caddr_t *)&softc->regs.addr, reg_offset, VGA_REG_SIZE, + &dev_attr, &softc->regs.handle); if (error != DDI_SUCCESS) goto fail; softc->regs.mapped = B_TRUE; @@ -501,9 +516,9 @@ vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) softc->fb_size = VGA_MEM_SIZE; error = ddi_regs_map_setup(devi, softc->fb_regno, - (caddr_t *)&softc->fb.addr, - mem_offset, softc->fb_size, - &dev_attr, &softc->fb.handle); + (caddr_t *)&softc->fb.addr, + mem_offset, softc->fb_size, + &dev_attr, &softc->fb.handle); if (error != DDI_SUCCESS) goto fail; softc->fb.mapped = B_TRUE; @@ -527,7 +542,7 @@ vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) goto fail; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), - DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) { + DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) { if (strcmp(cons, "graphics") == 0) { happyface_boot = 1; vgatext_silent = 1; @@ -589,6 +604,28 @@ vgatext_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) (void) ddi_soft_state_free(vgatext_softc_head, instance); return (DDI_SUCCESS); + case DDI_SUSPEND: + /* + * This is a generic VGA file, and therefore, cannot + * understand how to deal with suspend and resume on + * a generic interface. So we fail any attempt to + * suspend. At some point in the future, we might use + * this as an entrypoint for display drivers and this + * assumption may change. + * + * However, from a platform development perspective, + * it is important that this driver suspend if a + * developer is using a serial console and/or working + * on a framebuffer driver that will support suspend + * and resume. Therefore, we have this module tunable + * (purposely using a long name) that will allow for + * suspend it it is set. Otherwise we fail. + */ + if (vgatext_force_suspend != 0) + return (DDI_SUCCESS); + else + return (DDI_FAILURE); + default: cmn_err(CE_WARN, "vgatext_detach: unknown cmd 0x%x\n", cmd); return (DDI_FAILURE); @@ -676,59 +713,59 @@ do_gfx_ioctl(int cmd, intptr_t data, int mode, struct vgatext_softc *softc) case VIS_DEVINIT: - if (!(mode & FKIOCTL)) { - cmn_err(CE_CONT, kernel_only, "VIS_DEVINIT"); - return (ENXIO); - } + if (!(mode & FKIOCTL)) { + cmn_err(CE_CONT, kernel_only, "VIS_DEVINIT"); + return (ENXIO); + } - err = vgatext_devinit(softc, (struct vis_devinit *)data); - if (err != 0) { - cmn_err(CE_WARN, - "vgatext_ioctl: could not initialize console"); - return (err); - } - break; + err = vgatext_devinit(softc, (struct vis_devinit *)data); + if (err != 0) { + cmn_err(CE_WARN, + "vgatext_ioctl: could not initialize console"); + return (err); + } + break; case VIS_CONSCOPY: /* move */ - { - struct vis_conscopy pma; + { + struct vis_conscopy pma; - if (ddi_copyin((void *)data, &pma, - sizeof (struct vis_conscopy), mode)) - return (EFAULT); + if (ddi_copyin((void *)data, &pma, + sizeof (struct vis_conscopy), mode)) + return (EFAULT); - vgatext_cons_copy(softc, &pma); - break; - } + vgatext_cons_copy(softc, &pma); + break; + } case VIS_CONSDISPLAY: /* display */ - { - struct vis_consdisplay display_request; + { + struct vis_consdisplay display_request; - if (ddi_copyin((void *)data, &display_request, - sizeof (display_request), mode)) - return (EFAULT); + if (ddi_copyin((void *)data, &display_request, + sizeof (display_request), mode)) + return (EFAULT); - vgatext_cons_display(softc, &display_request); - break; - } + vgatext_cons_display(softc, &display_request); + break; + } case VIS_CONSCURSOR: - { - struct vis_conscursor cursor_request; + { + struct vis_conscursor cursor_request; - if (ddi_copyin((void *)data, &cursor_request, - sizeof (cursor_request), mode)) - return (EFAULT); + if (ddi_copyin((void *)data, &cursor_request, + sizeof (cursor_request), mode)) + return (EFAULT); - vgatext_cons_cursor(softc, &cursor_request); + vgatext_cons_cursor(softc, &cursor_request); - if (cursor_request.action == VIS_GET_CURSOR && - ddi_copyout(&cursor_request, (void *)data, - sizeof (cursor_request), mode)) - return (EFAULT); - break; - } + if (cursor_request.action == VIS_GET_CURSOR && + ddi_copyout(&cursor_request, (void *)data, + sizeof (cursor_request), mode)) + return (EFAULT); + break; + } case VIS_GETCMAP: case VIS_PUTCMAP: @@ -807,7 +844,7 @@ vgatext_kdsetmode(struct vgatext_softc *softc, int mode) softc->current_base = softc->text_base; if (softc->cursor.visible) { vgatext_set_cursor(softc, - softc->cursor.row, softc->cursor.col); + softc->cursor.row, softc->cursor.col); } vgatext_restore_colormap(softc); break; @@ -852,7 +889,7 @@ vgatext_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, } if (!(off >= VGA_MMAP_FB_BASE && - off < VGA_MMAP_FB_BASE + softc->fb_size)) { + off < VGA_MMAP_FB_BASE + softc->fb_size)) { cmn_err(CE_WARN, "vgatext: Can't map offset 0x%llx", off); return (-1); } @@ -863,8 +900,8 @@ vgatext_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, length = len; if ((err = devmap_devmem_setup(dhp, softc->devi, NULL, softc->fb_regno, - off - VGA_MMAP_FB_BASE, - length, PROT_ALL, 0, &dev_attr)) < 0) { + off - VGA_MMAP_FB_BASE, + length, PROT_ALL, 0, &dev_attr)) < 0) { return (err); } @@ -924,10 +961,10 @@ vgatext_cons_display(struct vgatext_softc *softc, struct vis_consdisplay *da) * system startup graphics. */ attr = (solaris_color_to_pc_color[da->bg_color & 0xf] << 4) - | solaris_color_to_pc_color[da->fg_color & 0xf]; + | solaris_color_to_pc_color[da->fg_color & 0xf]; string = da->data; addr = (struct cgatext *)softc->current_base - + (da->row * TEXT_COLS + da->col); + + (da->row * TEXT_COLS + da->col); for (i = 0; i < da->width; i++) { addr->ch = string[i]; addr->attr = attr; @@ -1130,20 +1167,20 @@ vgatext_set_text(struct vgatext_softc *softc) /* set sequencer registers */ vga_set_seq(&softc->regs, VGA_SEQ_RST_SYN, - (vga_get_seq(&softc->regs, VGA_SEQ_RST_SYN) & - ~VGA_SEQ_RST_SYN_NO_SYNC_RESET)); + (vga_get_seq(&softc->regs, VGA_SEQ_RST_SYN) & + ~VGA_SEQ_RST_SYN_NO_SYNC_RESET)); for (i = 1; i < NUM_SEQ_REG; i++) { vga_set_seq(&softc->regs, i, VGA_SEQ_TEXT[i]); } vga_set_seq(&softc->regs, VGA_SEQ_RST_SYN, - (vga_get_seq(&softc->regs, VGA_SEQ_RST_SYN) | - VGA_SEQ_RST_SYN_NO_ASYNC_RESET | - VGA_SEQ_RST_SYN_NO_SYNC_RESET)); + (vga_get_seq(&softc->regs, VGA_SEQ_RST_SYN) | + VGA_SEQ_RST_SYN_NO_ASYNC_RESET | + VGA_SEQ_RST_SYN_NO_SYNC_RESET)); /* set crt controller registers */ vga_set_crtc(&softc->regs, VGA_CRTC_VRE, - (vga_get_crtc(&softc->regs, VGA_CRTC_VRE) & - ~VGA_CRTC_VRE_LOCK)); + (vga_get_crtc(&softc->regs, VGA_CRTC_VRE) & + ~VGA_CRTC_VRE_LOCK)); for (i = 0; i < NUM_CRTC_REG; i++) { vga_set_crtc(&softc->regs, i, VGA_CRTC_TEXT[i]); } @@ -1161,8 +1198,8 @@ vgatext_set_text(struct vgatext_softc *softc) /* set palette */ for (i = 0; i < VGA_TEXT_CMAP_ENTRIES; i++) { vga_put_cmap(&softc->regs, i, VGA_TEXT_PALETTES[i][0] << 2, - VGA_TEXT_PALETTES[i][1] << 2, - VGA_TEXT_PALETTES[i][2] << 2); + VGA_TEXT_PALETTES[i][1] << 2, + VGA_TEXT_PALETTES[i][2] << 2); } for (i = VGA_TEXT_CMAP_ENTRIES; i < VGA8_CMAP_ENTRIES; i++) { vga_put_cmap(&softc->regs, i, 0, 0, 0); @@ -1185,10 +1222,10 @@ vgatext_init(struct vgatext_softc *softc) vga_set_atr(&softc->regs, VGA_ATR_MODE, atr_mode); #if defined(USE_BORDERS) vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR, - vga_get_atr(&softc->regs, VGA_BRIGHT_WHITE)); + vga_get_atr(&softc->regs, VGA_BRIGHT_WHITE)); #else vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR, - vga_get_atr(&softc->regs, VGA_BLACK)); + vga_get_atr(&softc->regs, VGA_BLACK)); #endif vgatext_setfont(softc); /* need selectable font? */ } @@ -1198,7 +1235,7 @@ static void vgatext_init_graphics(struct vgatext_softc *softc) { vga_set_atr(&softc->regs, VGA_ATR_BDR_CLR, - vga_get_atr(&softc->regs, VGA_BLACK)); + vga_get_atr(&softc->regs, VGA_BLACK)); } #endif @@ -1301,9 +1338,9 @@ vgatext_save_colormap(struct vgatext_softc *softc) } for (i = 0; i < VGA8_CMAP_ENTRIES; i++) { vga_get_cmap(&softc->regs, i, - &softc->colormap[i].red, - &softc->colormap[i].green, - &softc->colormap[i].blue); + &softc->colormap[i].red, + &softc->colormap[i].green, + &softc->colormap[i].blue); } } @@ -1317,9 +1354,9 @@ vgatext_restore_colormap(struct vgatext_softc *softc) } for (i = 0; i < VGA8_CMAP_ENTRIES; i++) { vga_put_cmap(&softc->regs, i, - softc->colormap[i].red, - softc->colormap[i].green, - softc->colormap[i].blue); + softc->colormap[i].red, + softc->colormap[i].green, + softc->colormap[i].blue); } } @@ -1354,7 +1391,7 @@ vgatext_get_pci_reg_index( pci_regspec_t *reg; if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, - "reg", (caddr_t)®, &length) != DDI_PROP_SUCCESS) { + "reg", (caddr_t)®, &length) != DDI_PROP_SUCCESS) { return (-1); } @@ -1413,7 +1450,7 @@ vgatext_get_isa_reg_index( struct regspec *reg; if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, - "reg", (caddr_t)®, &length) != DDI_PROP_SUCCESS) { + "reg", (caddr_t)®, &length) != DDI_PROP_SUCCESS) { return (-1); } diff --git a/usr/src/uts/intel/os/cpr_intel.c b/usr/src/uts/intel/os/cpr_intel.c new file mode 100644 index 0000000000..b34041386b --- /dev/null +++ b/usr/src/uts/intel/os/cpr_intel.c @@ -0,0 +1,75 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * cpr functions for supported sparc platforms + */ +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/cpr.h> +#include <sys/kmem.h> +#include <sys/errno.h> + +/* + * setup the original and new sets of property names/values + * Not relevant to S3, which is all we support for now. + */ +/*ARGSUSED*/ +int +cpr_default_setup(int alloc) +{ + return (0); +} + +void +cpr_send_notice(void) +{ + static char cstr[] = "\014" "\033[1P" "\033[18;21H"; + + prom_printf(cstr); + prom_printf("Saving System State. Please Wait... "); +} + +void +cpr_spinning_bar(void) +{ + static char *spin_strings[] = { "|\b", "/\b", "-\b", "\\\b" }; + static int idx; + + prom_printf(spin_strings[idx]); + if (++idx == 4) + idx = 0; +} + +void +cpr_resume_notice(void) +{ + static char cstr[] = "\014" "\033[1P" "\033[18;21H"; + + prom_printf(cstr); + prom_printf("Restoring System State. Please Wait... "); +} diff --git a/usr/src/uts/intel/os/name_to_major b/usr/src/uts/intel/os/name_to_major index 9d983ec052..28810d57b0 100644 --- a/usr/src/uts/intel/os/name_to_major +++ b/usr/src/uts/intel/os/name_to_major @@ -127,6 +127,8 @@ evtchn 197 xdb 199 domcaps 200 balloon 201 +acpippm 202 +srn 203 did 239 lx_ptm 240 lx_systrace 241 diff --git a/usr/src/uts/intel/promif/prom_env.c b/usr/src/uts/intel/promif/prom_env.c index 4b43f678ef..73b2a08af6 100644 --- a/usr/src/uts/intel/promif/prom_env.c +++ b/usr/src/uts/intel/promif/prom_env.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,6 +47,7 @@ static promif_owrap_t nullwrapper = static promif_owrap_t *wrapper = &nullwrapper; static promif_owrap_t pmwrapper; +static promif_owrap_t *saved_wrapper; promif_owrap_t *promif_preout(void) @@ -69,3 +70,17 @@ prom_set_outfuncs(void (*pref)(void), void (*postf)(void)) pmwrapper.postout = postf; wrapper = &pmwrapper; } + +void +prom_suspend_prepost(void) +{ + saved_wrapper = wrapper; + wrapper = &nullwrapper; +} + +void +prom_resume_prepost(void) +{ + wrapper = saved_wrapper; + saved_wrapper = NULL; +} diff --git a/usr/src/uts/intel/srn/Makefile b/usr/src/uts/intel/srn/Makefile new file mode 100755 index 0000000000..8146241688 --- /dev/null +++ b/usr/src/uts/intel/srn/Makefile @@ -0,0 +1,84 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# uts/intel/srn/Makefile +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# This makefile drives the production of the srn driver +# +# intel architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. + +# +# Define the module and object file sets. +# +MODULE = srn +OBJECTS = $(SRN_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(SRN_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/common/io + +# +# Include common rules. +# +include $(UTSBASE)/intel/Makefile.intel + +# +# Define targets +# +ALL_TARGET = $(BINARY) $(SRC_CONFILE) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/intel/Makefile.targ diff --git a/usr/src/uts/intel/sys/acpica.h b/usr/src/uts/intel/sys/acpica.h index b760afcb97..40e830fd05 100644 --- a/usr/src/uts/intel/sys/acpica.h +++ b/usr/src/uts/intel/sys/acpica.h @@ -128,6 +128,8 @@ extern ACPI_STATUS acpica_get_handle(dev_info_t *, ACPI_HANDLE *); extern ACPI_STATUS acpica_eval_int(ACPI_HANDLE, char *, int *); extern void acpica_map_cpu(processorid_t, MADT_PROCESSOR_APIC *); extern void acpica_build_processor_map(); +extern void acpica_ddi_save_resources(dev_info_t *); +extern void acpica_ddi_restore_resources(dev_info_t *); #ifdef __cplusplus } diff --git a/usr/src/uts/intel/sys/promif.h b/usr/src/uts/intel/sys/promif.h index 20ce5c2db1..ee7e138f1e 100644 --- a/usr/src/uts/intel/sys/promif.h +++ b/usr/src/uts/intel/sys/promif.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -219,6 +218,9 @@ typedef struct promif_owrap { void (*postout)(void); } promif_owrap_t; +extern void prom_suspend_prepost(void); +extern void prom_resume_prepost(void); + /* * WAN boot key storage interface */ |