[BACK]Return to apm.c CVS log [TXT][DIR] Up to [local] / sys / arch / macppc / dev

Annotation of sys/arch/macppc/dev/apm.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: apm.c,v 1.12 2006/01/18 23:21:17 miod Exp $   */
                      2:
                      3: /*-
                      4:  * Copyright (c) 2001 Alexander Guy.  All rights reserved.
                      5:  * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved.
                      6:  * Copyright (c) 1995 John T. Kohl.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  */
                     37:
                     38: #include "apm.h"
                     39:
                     40: #if NAPM > 1
                     41: #error only one APM emulation device may be configured
                     42: #endif
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/proc.h>
                     48: #include <sys/device.h>
                     49: #include <sys/fcntl.h>
                     50: #include <sys/ioctl.h>
                     51: #include <sys/event.h>
                     52:
                     53: #include <machine/conf.h>
                     54: #include <machine/cpu.h>
                     55: #include <machine/apmvar.h>
                     56:
                     57: #include <dev/adb/adb.h>
                     58: #include <macppc/dev/adbvar.h>
                     59: #include <macppc/dev/pm_direct.h>
                     60:
                     61: #if defined(APMDEBUG)
                     62: #define DPRINTF(x)     printf x
                     63: #else
                     64: #define        DPRINTF(x)      /**/
                     65: #endif
                     66:
                     67: struct apm_softc {
                     68:        struct device sc_dev;
                     69:        struct klist sc_note;
                     70:        int    sc_flags;
                     71: };
                     72:
                     73: int apmmatch(struct device *, void *, void *);
                     74: void apmattach(struct device *, struct device *, void *);
                     75:
                     76: struct cfattach apm_ca = {
                     77:        sizeof(struct apm_softc), apmmatch, apmattach
                     78: };
                     79:
                     80: struct cfdriver apm_cd = {
                     81:        NULL, "apm", DV_DULL
                     82: };
                     83:
                     84: #define        APMUNIT(dev)    (minor(dev)&0xf0)
                     85: #define        APMDEV(dev)     (minor(dev)&0x0f)
                     86: #define APMDEV_NORMAL  0
                     87: #define APMDEV_CTL     8
                     88:
                     89: void filt_apmrdetach(struct knote *kn);
                     90: int filt_apmread(struct knote *kn, long hint);
                     91: int apmkqfilter(dev_t dev, struct knote *kn);
                     92:
                     93: struct filterops apmread_filtops =
                     94:        { 1, NULL, filt_apmrdetach, filt_apmread};
                     95:
                     96: /*
                     97:  * Flags to control kernel display
                     98:  *     SCFLAG_NOPRINT:         do not output APM power messages due to
                     99:  *                             a power change event.
                    100:  *
                    101:  *     SCFLAG_PCTPRINT:        do not output APM power messages due to
                    102:  *                             to a power change event unless the battery
                    103:  *                             percentage changes.
                    104:  */
                    105:
                    106: #define SCFLAG_NOPRINT 0x0008000
                    107: #define SCFLAG_PCTPRINT        0x0004000
                    108: #define SCFLAG_PRINT   (SCFLAG_NOPRINT|SCFLAG_PCTPRINT)
                    109:
                    110: #define        SCFLAG_OREAD    (1 << 0)
                    111: #define        SCFLAG_OWRITE   (1 << 1)
                    112: #define        SCFLAG_OPEN     (SCFLAG_OREAD|SCFLAG_OWRITE)
                    113:
                    114:
                    115: int
                    116: apmmatch(struct device *parent, void *match, void *aux)
                    117: {
                    118:        struct adb_attach_args *aa = (void *)aux;
                    119:        if (aa->origaddr != ADBADDR_APM ||
                    120:            aa->handler_id != ADBADDR_APM ||
                    121:            aa->adbaddr != ADBADDR_APM)
                    122:                return 0;
                    123:
                    124:        if (adbHardware != ADB_HW_PMU)
                    125:                return 0;
                    126:
                    127:        return 1;
                    128: }
                    129:
                    130: void
                    131: apmattach(struct device *parent, struct device *self, void *aux)
                    132: {
                    133:        struct pmu_battery_info info;
                    134:
                    135:        pm_battery_info(0, &info);
                    136:
                    137:        printf(": battery flags 0x%X, ", info.flags);
                    138:        printf("%d%% charged\n", ((info.cur_charge * 100) / info.max_charge));
                    139: }
                    140:
                    141: int
                    142: apmopen(dev_t dev, int flag, int mode, struct proc *p)
                    143: {
                    144:        struct apm_softc *sc;
                    145:        int error = 0;
                    146:
                    147:        /* apm0 only */
                    148:        if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
                    149:            !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
                    150:                return ENXIO;
                    151:
                    152:        DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n",
                    153:            APMDEV(dev), p->p_pid, flag, mode));
                    154:
                    155:        switch (APMDEV(dev)) {
                    156:        case APMDEV_CTL:
                    157:                if (!(flag & FWRITE)) {
                    158:                        error = EINVAL;
                    159:                        break;
                    160:                }
                    161:                if (sc->sc_flags & SCFLAG_OWRITE) {
                    162:                        error = EBUSY;
                    163:                        break;
                    164:                }
                    165:                sc->sc_flags |= SCFLAG_OWRITE;
                    166:                break;
                    167:        case APMDEV_NORMAL:
                    168:                if (!(flag & FREAD) || (flag & FWRITE)) {
                    169:                        error = EINVAL;
                    170:                        break;
                    171:                }
                    172:                sc->sc_flags |= SCFLAG_OREAD;
                    173:                break;
                    174:        default:
                    175:                error = ENXIO;
                    176:                break;
                    177:        }
                    178:        return error;
                    179: }
                    180:
                    181: int
                    182: apmclose(dev_t dev, int flag, int mode, struct proc *p)
                    183: {
                    184:        struct apm_softc *sc;
                    185:
                    186:        /* apm0 only */
                    187:        if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
                    188:            !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
                    189:                return ENXIO;
                    190:
                    191:        DPRINTF(("apmclose: pid %d flag %x mode %x\n", p->p_pid, flag, mode));
                    192:
                    193:        switch (APMDEV(dev)) {
                    194:        case APMDEV_CTL:
                    195:                sc->sc_flags &= ~SCFLAG_OWRITE;
                    196:                break;
                    197:        case APMDEV_NORMAL:
                    198:                sc->sc_flags &= ~SCFLAG_OREAD;
                    199:                break;
                    200:        }
                    201:        return 0;
                    202: }
                    203:
                    204: int
                    205: apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                    206: {
                    207:        struct apm_softc *sc;
                    208:        struct pmu_battery_info batt;
                    209:        struct apm_power_info *power;
                    210:        int error = 0;
                    211:
                    212:        /* apm0 only */
                    213:        if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
                    214:            !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
                    215:                return ENXIO;
                    216:
                    217:        switch (cmd) {
                    218:                /* some ioctl names from linux */
                    219:        case APM_IOC_STANDBY:
                    220:                if ((flag & FWRITE) == 0)
                    221:                        error = EBADF;
                    222:                break;
                    223:        case APM_IOC_SUSPEND:
                    224:                if ((flag & FWRITE) == 0)
                    225:                        error = EBADF;
                    226:                break;
                    227:        case APM_IOC_PRN_CTL:
                    228:                if ((flag & FWRITE) == 0)
                    229:                        error = EBADF;
                    230:                else {
                    231:                        int flag = *(int *)data;
                    232:                        DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag ));
                    233:                        switch (flag) {
                    234:                        case APM_PRINT_ON:      /* enable printing */
                    235:                                sc->sc_flags &= ~SCFLAG_PRINT;
                    236:                                break;
                    237:                        case APM_PRINT_OFF: /* disable printing */
                    238:                                sc->sc_flags &= ~SCFLAG_PRINT;
                    239:                                sc->sc_flags |= SCFLAG_NOPRINT;
                    240:                                break;
                    241:                        case APM_PRINT_PCT: /* disable some printing */
                    242:                                sc->sc_flags &= ~SCFLAG_PRINT;
                    243:                                sc->sc_flags |= SCFLAG_PCTPRINT;
                    244:                                break;
                    245:                        default:
                    246:                                error = EINVAL;
                    247:                                break;
                    248:                        }
                    249:                }
                    250:                break;
                    251:        case APM_IOC_DEV_CTL:
                    252:                if ((flag & FWRITE) == 0)
                    253:                        error = EBADF;
                    254:                break;
                    255:        case APM_IOC_GETPOWER:
                    256:                power = (struct apm_power_info *)data;
                    257:
                    258:                pm_battery_info(0, &batt);
                    259:
                    260:                power->ac_state = ((batt.flags & PMU_PWR_AC_PRESENT) ?
                    261:                    APM_AC_ON : APM_AC_OFF);
                    262:                power->battery_life =
                    263:                    ((batt.cur_charge * 100) / batt.max_charge);
                    264:
                    265:                /*
                    266:                 * If the battery is charging, return the minutes left until
                    267:                 * charging is complete. apmd knows this.
                    268:                 */
                    269:
                    270:                if (!(batt.flags & PMU_PWR_BATT_PRESENT)) {
                    271:                        power->battery_state = APM_BATT_UNKNOWN;
                    272:                        power->minutes_left = 0;
                    273:                        power->battery_life = 0;
                    274:                } else if ((power->ac_state == APM_AC_ON) &&
                    275:                           (batt.draw > 0)) {
                    276:                        power->minutes_left =
                    277:                            (((batt.max_charge - batt.cur_charge) * 3600) /
                    278:                            batt.draw) / 60;
                    279:                        power->battery_state = APM_BATT_CHARGING;
                    280:                } else {
                    281:                        power->minutes_left =
                    282:                            ((batt.cur_charge * 3600) / (-batt.draw)) / 60;
                    283:
                    284:                        /* XXX - Arbitrary */
                    285:                        if (power->battery_life > 60)
                    286:                                power->battery_state = APM_BATT_HIGH;
                    287:                        else if (power->battery_life < 10)
                    288:                                power->battery_state = APM_BATT_CRITICAL;
                    289:                        else
                    290:                                power->battery_state = APM_BATT_LOW;
                    291:                }
                    292:                break;
                    293:
                    294:        default:
                    295:                error = ENOTTY;
                    296:        }
                    297:
                    298:        return error;
                    299: }
                    300:
                    301: void
                    302: filt_apmrdetach(struct knote *kn)
                    303: {
                    304:        struct apm_softc *sc = (struct apm_softc *)kn->kn_hook;
                    305:
                    306:        SLIST_REMOVE(&sc->sc_note, kn, knote, kn_selnext);
                    307: }
                    308:
                    309: int
                    310: filt_apmread(struct knote *kn, long hint)
                    311: {
                    312:        /* XXX weird kqueue_scan() semantics */
                    313:        if (hint && !kn->kn_data)
                    314:                kn->kn_data = (int)hint;
                    315:
                    316:        return (1);
                    317: }
                    318:
                    319: int
                    320: apmkqfilter(dev_t dev, struct knote *kn)
                    321: {
                    322:        struct apm_softc *sc;
                    323:
                    324:        /* apm0 only */
                    325:        if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
                    326:            !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
                    327:                return ENXIO;
                    328:
                    329:        switch (kn->kn_filter) {
                    330:        case EVFILT_READ:
                    331:                kn->kn_fop = &apmread_filtops;
                    332:                break;
                    333:        default:
                    334:                return (1);
                    335:        }
                    336:
                    337:        kn->kn_hook = (caddr_t)sc;
                    338:        SLIST_INSERT_HEAD(&sc->sc_note, kn, kn_selnext);
                    339:
                    340:        return (0);
                    341: }

CVSweb