FreeBSD/sys/i386/bios/apm.c
/*
 * Attach APM:
 *
 * Initialize APM driver
 */
Attach APM:
Initialize APM driver
Attach APM : Initialize APM driver
static int
apm_attach(device_t dev)
{
	struct apm_softc	*sc = &apm_softc;
	int			drv_version;
#ifdef PC98
	int			rid;
#endif
	mtx_init(&sc->mtx, device_get_nameunit(dev), "apm", MTX_DEF);
	cv_init(&sc->cv, "cbb cv");
#ifndef PC98
	if (device_get_flags(dev) & 0x20)
		atrtcclock_disable = 1;
#endif
	sc->initialized = 0;
	sc->active = 0;
	sc->always_halt_cpu = 1;
	getenv_int("debug.apm_debug", &apm_debug);
	APM_DPRINT("apm: APM BIOS version %04lx\n",  apm_version);
	APM_DPRINT("apm: Code16 0x%08x, Data 0x%08x\n",
	    sc->bios.seg.code16.base, sc->bios.seg.data.base);
	APM_DPRINT("apm: Code entry 0x%08x, Idling CPU %s, Management %s\n",
	    sc->bios.entry, is_enabled(sc->slow_idle_cpu),
	    is_enabled(!sc->disabled));
	APM_DPRINT("apm: CS_limit=0x%x, DS_limit=0x%x\n",
	    sc->bios.seg.code16.limit, sc->bios.seg.data.limit);
#ifdef PC98
	rid = 0;
	sc->sc_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
			 APM_NECSMM_PORT, ~0, APM_NECSMM_PORTSZ, RF_ACTIVE);
	if (sc->sc_res == NULL)
		panic("%s: counldn't map I/O ports", device_get_name(dev));
	sc->sc_iot = rman_get_bustag(sc->sc_res);
	sc->sc_ioh = rman_get_bushandle(sc->sc_res);
	if (apm_version==0x112 || apm_version==0x111 || apm_version==0x110)
		apm_necsmm_addr = APM_NECSMM_PORT;
	else
		apm_necsmm_addr = 0;
	apm_necsmm_mask = ~APM_NECSMM_EN;
#endif 
	drv_version = apm_version > 0x102 ? 0x102 : apm_version;
	for (; drv_version > 0x100; drv_version--)
		if (apm_driver_version(drv_version) == 0)
			break;
	sc->minorversion = ((drv_version & 0x00f0) >>  4) * 10 +
		((drv_version & 0x000f) >> 0);
	sc->majorversion = ((drv_version & 0xf000) >> 12) * 10 +
		((apm_version & 0x0f00) >> 8);
	sc->intversion = INTVERSION(sc->majorversion, sc->minorversion);
	if (sc->intversion >= INTVERSION(1, 1))
		APM_DPRINT("apm: Engaged control %s\n", is_enabled(!sc->disengaged));
	device_printf(dev, "found APM BIOS v%ld.%ld, connected at v%d.%d\n",
	       ((apm_version & 0xf000) >> 12) * 10 + ((apm_version & 0x0f00) >> 8),
	       ((apm_version & 0x00f0) >> 4) * 10 + ((apm_version & 0x000f) >> 0),
	       sc->majorversion, sc->minorversion);
	APM_DPRINT("apm: Slow Idling CPU %s\n", is_enabled(sc->slow_idle_cpu));
	if (sc->disabled) {
		if (apm_enable_disable_pm(1)) {
			APM_DPRINT("apm: *Warning* enable function failed! [%x]\n",
			    (sc->bios.r.eax >> 8) & 0xff);
		}
	}
	if (sc->intversion >= INTVERSION(1, 1) && sc->disengaged) {
		if (apm_engage_disengage_pm(1)) {
			APM_DPRINT("apm: *Warning* engage function failed err=[%x]",
			    (sc->bios.r.eax >> 8) & 0xff);
			APM_DPRINT(" (Docked or using external power?).\n");
		}
	}
	EVENTHANDLER_REGISTER(shutdown_final, apm_power_off, NULL, 
			      SHUTDOWN_PRI_LAST);
	power_pm_register(POWER_PM_TYPE_APM, apm_pm_func, sc);
	sc->initialized = 1;
	sc->suspending = 0;
	sc->running = 0;
	make_dev(&apm_cdevsw, APMDEV_NORMAL,
	    UID_ROOT, GID_OPERATOR, 0664, "apm");
	make_dev(&apm_cdevsw, APMDEV_CTL,
	    UID_ROOT, GID_OPERATOR, 0660, "apmctl");
	return 0;
}
static int apm_attach ( device_t dev ) { struct apm_softc * sc = & apm_softc ; int drv_version ; #ifdef PC98 int rid ; #endif mtx_init ( & sc -> mtx , device_get_nameunit ( dev ) , " " , MTX_DEF ) ; cv_init ( & sc -> cv , " " ) ; #ifndef PC98 if ( device_get_flags ( dev ) & 0x20 ) atrtcclock_disable = 1 ; #endif sc -> initialized = 0 ; sc -> active = 0 ; sc -> always_halt_cpu = 1 ; getenv_int ( " " , & apm_debug ) ; APM_DPRINT ( " \n " , apm_version ) ; APM_DPRINT ( " \n " , sc -> bios . seg . code16 . base , sc -> bios . seg . data . base ) ; APM_DPRINT ( " \n " , sc -> bios . entry , is_enabled ( sc -> slow_idle_cpu ) , is_enabled ( ! sc -> disabled ) ) ; APM_DPRINT ( " \n " , sc -> bios . seg . code16 . limit , sc -> bios . seg . data . limit ) ; #ifdef PC98 rid = 0 ; sc -> sc_res = bus_alloc_resource ( dev , SYS_RES_IOPORT , & rid , APM_NECSMM_PORT , ~ 0 , APM_NECSMM_PORTSZ , RF_ACTIVE ) ; if ( sc -> sc_res == NULL ) panic ( " " , device_get_name ( dev ) ) ; sc -> sc_iot = rman_get_bustag ( sc -> sc_res ) ; sc -> sc_ioh = rman_get_bushandle ( sc -> sc_res ) ; if ( apm_version == 0x112 || apm_version == 0x111 || apm_version == 0x110 ) apm_necsmm_addr = APM_NECSMM_PORT ; else apm_necsmm_addr = 0 ; apm_necsmm_mask = ~ APM_NECSMM_EN ; #endif drv_version = apm_version > 0x102 ? 0x102 : apm_version ; for ( ; drv_version > 0x100 ; drv_version -- ) if ( apm_driver_version ( drv_version ) == 0 ) break ; sc -> minorversion = ( ( drv_version & 0x00f0 ) >> 4 ) * 10 + ( ( drv_version & 0x000f ) >> 0 ) ; sc -> majorversion = ( ( drv_version & 0xf000 ) >> 12 ) * 10 + ( ( apm_version & 0x0f00 ) >> 8 ) ; sc -> intversion = INTVERSION ( sc -> majorversion , sc -> minorversion ) ; if ( sc -> intversion >= INTVERSION ( 1 , 1 ) ) APM_DPRINT ( " \n " , is_enabled ( ! sc -> disengaged ) ) ; device_printf ( dev , " \n " , ( ( apm_version & 0xf000 ) >> 12 ) * 10 + ( ( apm_version & 0x0f00 ) >> 8 ) , ( ( apm_version & 0x00f0 ) >> 4 ) * 10 + ( ( apm_version & 0x000f ) >> 0 ) , sc -> majorversion , sc -> minorversion ) ; APM_DPRINT ( " \n " , is_enabled ( sc -> slow_idle_cpu ) ) ; if ( sc -> disabled ) { if ( apm_enable_disable_pm ( 1 ) ) { APM_DPRINT ( " \n " , ( sc -> bios . r . eax >> 8 ) & 0xff ) ; } } if ( sc -> intversion >= INTVERSION ( 1 , 1 ) && sc -> disengaged ) { if ( apm_engage_disengage_pm ( 1 ) ) { APM_DPRINT ( " " , ( sc -> bios . r . eax >> 8 ) & 0xff ) ; APM_DPRINT ( " \n " ) ; } } EVENTHANDLER_REGISTER ( shutdown_final , apm_power_off , NULL , SHUTDOWN_PRI_LAST ) ; power_pm_register ( POWER_PM_TYPE_APM , apm_pm_func , sc ) ; sc -> initialized = 1 ; sc -> suspending = 0 ; sc -> running = 0 ; make_dev ( & apm_cdevsw , APMDEV_NORMAL , UID_ROOT , GID_OPERATOR , 0664 , " " ) ; make_dev ( & apm_cdevsw , APMDEV_CTL , UID_ROOT , GID_OPERATOR , 0660 , " " ) ; return 0 ; }
Attach APM:
 Initialize APM driver
Attach APM : Initialize APM driver
/* Must be externally enabled */ /* Always call HLT in idle loop */ /* print bootstrap messages */ /* PC98 */ /*
         * In one test, apm bios version was 1.02; an attempt to register
         * a 1.04 driver resulted in a 1.00 connection!  Registering a
         * 1.02 driver resulted in a 1.02 connection.
         */ /* enable power management */ /* engage power managment (APM 1.1 or later) */ /* Power the system off using APM */ /* Register APM again to pass the correct argument of pm_func. */