diff options
author | mdodd <mdodd@FreeBSD.org> | 2003-03-25 05:19:18 +0000 |
---|---|---|
committer | mdodd <mdodd@FreeBSD.org> | 2003-03-25 05:19:18 +0000 |
commit | 012abb85fbb76e777aca3b02c1b9fc912a074ca0 (patch) | |
tree | 93c1e9979515fec38506fe5d4a281800946773c4 /sys/i386/bios/apm.c | |
parent | c66444c488172bdba9e7c233abae45f0a8efe753 (diff) | |
download | FreeBSD-src-012abb85fbb76e777aca3b02c1b9fc912a074ca0.zip FreeBSD-src-012abb85fbb76e777aca3b02c1b9fc912a074ca0.tar.gz |
Merge PC98 support.
Diffstat (limited to 'sys/i386/bios/apm.c')
-rw-r--r-- | sys/i386/bios/apm.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c index a4a965f..a220696 100644 --- a/sys/i386/bios/apm.c +++ b/sys/i386/bios/apm.c @@ -43,6 +43,10 @@ #include <machine/stdarg.h> #include <machine/vm86.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> + #include <vm/vm.h> #include <vm/pmap.h> #include <vm/vm_param.h> @@ -71,6 +75,19 @@ int apm_evindex; #define APMDEV_NORMAL 0 #define APMDEV_CTL 8 +#ifdef PC98 +extern int bios32_apm98(struct bios_regs *, u_int, u_short); + +/* PC98's SMM definition */ +#define APM_NECSMM_PORT 0x6b8e +#define APM_NECSMM_PORTSZ 1 +#define APM_NECSMM_EN 0x10 +static __inline void apm_enable_smm(struct apm_softc *); +static __inline void apm_disable_smm(struct apm_softc *); +int apm_necsmm_addr; +u_int32_t apm_necsmm_mask; +#endif + static struct apmhook *hook[NAPM_HOOK]; /* XXX */ #define is_enabled(foo) ((foo) ? "enabled" : "disabled") @@ -113,6 +130,30 @@ SYSCTL_INT(_machdep, OID_AUTO, apm_suspend_delay, CTLFLAG_RW, &apm_suspend_delay SYSCTL_INT(_machdep, OID_AUTO, apm_standby_delay, CTLFLAG_RW, &apm_standby_delay, 1, ""); SYSCTL_INT(_debug, OID_AUTO, apm_debug, CTLFLAG_RW, &apm_debug, 0, ""); +#ifdef PC98 +static __inline void +apm_enable_smm(sc) + struct apm_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + if (apm_necsmm_addr != 0) + bus_space_write_1(iot, ioh, 0, + (bus_space_read_1(iot, ioh, 0) | ~apm_necsmm_mask)); +} + +static __inline void +apm_disable_smm(sc) + struct apm_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + if (apm_necsmm_addr != 0) + bus_space_write_1(iot, ioh, 0, + (bus_space_read_1(iot, ioh, 0) & apm_necsmm_mask)); +} +#endif + /* * return 0 if the function successfull, * return 1 if the function unsuccessfull, @@ -132,6 +173,12 @@ apm_bioscall(void) } sc->bios_busy = 1; +#ifdef PC98 + set_bios_selectors(&sc->bios.seg, BIOSCODE_FLAG | BIOSDATA_FLAG); + if (bios32_apm98(&sc->bios.r, sc->bios.entry, + GSEL(GBIOSCODE32_SEL, SEL_KPL)) != 0) + return 1; +#else if (sc->connectmode == APM_PROT32CONNECT) { set_bios_selectors(&sc->bios.seg, BIOSCODE_FLAG | BIOSDATA_FLAG); @@ -140,6 +187,7 @@ apm_bioscall(void) } else { errno = bios16(&sc->bios, NULL); } +#endif sc->bios_busy = 0; return (errno); } @@ -152,6 +200,11 @@ apm_check_function_supported(u_int version, u_int func) if (func == APM_DRVVERSION) { return (1); } +#ifdef PC98 + if (func == APM_GETPWSTATUS) { + return (1); + } +#endif switch (version) { case INTVERSION(1, 0): @@ -250,11 +303,17 @@ apm_suspend_system(int state) sc->bios.r.ecx = state; sc->bios.r.edx = 0; +#ifdef PC98 + apm_disable_smm(sc); +#endif if (apm_bioscall()) { printf("Entire system suspend failure: errcode = %d\n", 0xff & (sc->bios.r.eax >> 8)); return 1; } +#ifdef PC98 + apm_enable_smm(sc); +#endif return 0; } @@ -793,6 +852,9 @@ apm_probe(device_t dev) struct vm86frame vmf; struct apm_softc *sc = &apm_softc; int disabled, flags; +#ifdef PC98 + int rid; +#endif device_set_desc(dev, "APM BIOS"); @@ -841,6 +903,38 @@ apm_probe(device_t dev) vmf.vmf_bx = 0; vm86_intcall(APM_INT, &vmf); /* disconnect, just in case */ +#ifdef PC98 + /* PC98 have bogos APM 32bit BIOS */ + if ((vmf.vmf_cx & APM_32BIT_SUPPORT) == 0) + return ENXIO; + rid = 0; + bus_set_resource(dev, SYS_RES_IOPORT, rid, + APM_NECSMM_PORT, APM_NECSMM_PORTSZ); + 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) { + printf("apm: cannot open NEC smm device\n"); + return ENXIO; + } + bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_res); + + vmf.vmf_ah = APM_BIOS; + vmf.vmf_al = APM_PROT32CONNECT; + vmf.vmf_bx = 0; + if (vm86_intcall(APM_INT, &vmf)) { + printf("apm: 32-bit connection error.\n"); + return (ENXIO); + } + + sc->bios.seg.code32.base = (vmf.vmf_ax << 4) + APM_KERNBASE; + sc->bios.seg.code32.limit = 0xffff; + sc->bios.seg.code16.base = (vmf.vmf_cx << 4) + APM_KERNBASE; + sc->bios.seg.code16.limit = 0xffff; + sc->bios.seg.data.base = (vmf.vmf_dx << 4) + APM_KERNBASE; + sc->bios.seg.data.limit = 0xffff; + sc->bios.entry = vmf.vmf_ebx; + sc->connectmode = APM_PROT32CONNECT; +#else if ((vmf.vmf_cx & APM_32BIT_SUPPORT) != 0) { vmf.vmf_ah = APM_BIOS; vmf.vmf_al = APM_PROT32CONNECT; @@ -873,6 +967,7 @@ apm_probe(device_t dev) sc->bios.entry = vmf.vmf_bx; sc->connectmode = APM_PROT16CONNECT; } +#endif return(0); } @@ -1006,6 +1101,9 @@ apm_processevent(void) break; } } while (apm_event != PMEV_NOEVENT); +#ifdef PC98 + apm_disable_smm(sc); +#endif } /* @@ -1020,6 +1118,9 @@ apm_attach(device_t dev) struct apm_softc *sc = &apm_softc; int flags; int drv_version; +#ifdef PC98 + int rid; +#endif if (resource_int_value("apm", 0, "flags", &flags) != 0) flags = 0; @@ -1047,6 +1148,22 @@ apm_attach(device_t dev) 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 /* 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 |