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

Annotation of sys/arch/macppc/dev/pm_direct.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pm_direct.c,v 1.22 2007/02/18 19:33:48 gwk Exp $      */
        !             2: /*     $NetBSD: pm_direct.c,v 1.9 2000/06/08 22:10:46 tsubai Exp $     */
        !             3:
        !             4: /*
        !             5:  * Copyright (C) 1997 Takashi Hamada
        !             6:  * 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 Takashi Hamada
        !            19:  * 4. The name of the author may not be used to endorse or promote products
        !            20:  *    derived from this software without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        !            31:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: #ifdef DEBUG
        !            35: #ifndef ADB_DEBUG
        !            36: #define ADB_DEBUG
        !            37: #endif
        !            38: #endif
        !            39:
        !            40: /* #define     PM_GRAB_SI      1 */
        !            41:
        !            42: #include <sys/param.h>
        !            43: #include <sys/cdefs.h>
        !            44: #include <sys/device.h>
        !            45: #include <sys/systm.h>
        !            46:
        !            47: #include <machine/cpu.h>
        !            48:
        !            49: #include <dev/adb/adb.h>
        !            50: #include <macppc/dev/adbvar.h>
        !            51: #include <macppc/dev/pm_direct.h>
        !            52: #include <macppc/dev/viareg.h>
        !            53:
        !            54: /* hardware dependent values */
        !            55: #define ADBDelay 100           /* XXX */
        !            56:
        !            57: /* define the types of the Power Manager */
        !            58: #define PM_HW_UNKNOWN          0x00    /* don't know */
        !            59: #define        PM_HW_PB5XX             0x02    /* PowerBook Duo and 5XX series */
        !            60:
        !            61: /* useful macros */
        !            62: #define PM_SR()                        read_via_reg(VIA1, vSR)
        !            63: #define PM_VIA_INTR_ENABLE()   write_via_reg(VIA1, vIER, 0x90)
        !            64: #define PM_VIA_INTR_DISABLE()  write_via_reg(VIA1, vIER, 0x10)
        !            65: #define PM_VIA_CLR_INTR()      write_via_reg(VIA1, vIFR, 0x90)
        !            66: #if 0
        !            67: #define PM_SET_STATE_ACKON()   via_reg_or(VIA2, vBufB, 0x04)
        !            68: #define PM_SET_STATE_ACKOFF()  via_reg_and(VIA2, vBufB, ~0x04)
        !            69: #define PM_IS_ON               (0x02 == (read_via_reg(VIA2, vBufB) & 0x02))
        !            70: #define PM_IS_OFF              (0x00 == (read_via_reg(VIA2, vBufB) & 0x02))
        !            71: #else
        !            72: #define PM_SET_STATE_ACKON()   via_reg_or(VIA2, vBufB, 0x10)
        !            73: #define PM_SET_STATE_ACKOFF()  via_reg_and(VIA2, vBufB, ~0x10)
        !            74: #define PM_IS_ON               (0x08 == (read_via_reg(VIA2, vBufB) & 0x08))
        !            75: #define PM_IS_OFF              (0x00 == (read_via_reg(VIA2, vBufB) & 0x08))
        !            76: #endif
        !            77:
        !            78: /*
        !            79:  * Variables for internal use
        !            80:  */
        !            81: int    pmHardware = PM_HW_UNKNOWN;
        !            82:
        !            83: /* these values shows that number of data returned after 'send' cmd is sent */
        !            84: signed char pm_send_cmd_type[] = {
        !            85:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !            86:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !            87:        0x01, 0x01,   -1,   -1,   -1,   -1,   -1,   -1,
        !            88:        0x00, 0x00,   -1,   -1,   -1,   -1,   -1, 0x00,
        !            89:          -1, 0x00, 0x02, 0x01, 0x01,   -1,   -1,   -1,
        !            90:        0x00,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !            91:        0x04, 0x14,   -1, 0x03,   -1,   -1,   -1,   -1,
        !            92:        0x00, 0x00, 0x02, 0x02,   -1,   -1,   -1,   -1,
        !            93:        0x01, 0x01,   -1,   -1,   -1,   -1,   -1,   -1,
        !            94:        0x00, 0x00,   -1,   -1, 0x01,   -1,   -1,   -1,
        !            95:        0x01, 0x00, 0x02, 0x02,   -1, 0x01, 0x03, 0x01,
        !            96:        0x00, 0x01, 0x00, 0x00, 0x00,   -1,   -1,   -1,
        !            97:        0x02,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !            98:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   -1,   -1,
        !            99:        0x01, 0x01, 0x01,   -1,   -1,   -1,   -1,   -1,
        !           100:        0x00, 0x00,   -1,   -1,   -1,   -1, 0x04, 0x04,
        !           101:        0x04,   -1, 0x00,   -1,   -1,   -1,   -1,   -1,
        !           102:        0x00,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           103:        0x01, 0x02,   -1,   -1,   -1,   -1,   -1,   -1,
        !           104:        0x00, 0x00,   -1,   -1,   -1,   -1,   -1,   -1,
        !           105:        0x02, 0x02, 0x02, 0x04,   -1, 0x00,   -1,   -1,
        !           106:        0x01, 0x01, 0x03, 0x02,   -1,   -1,   -1,   -1,
        !           107:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           108:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           109:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           110:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           111:        0x00,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           112:        0x01, 0x01,   -1,   -1, 0x00, 0x00,   -1,   -1,
        !           113:          -1, 0x04, 0x00,   -1,   -1,   -1,   -1,   -1,
        !           114:        0x03,   -1, 0x00,   -1, 0x00,   -1,   -1, 0x00,
        !           115:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           116:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1
        !           117: };
        !           118:
        !           119: /* these values shows that number of data returned after 'receive' cmd is sent */
        !           120: signed char pm_receive_cmd_type[] = {
        !           121:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           122:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           123:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           124:        0x02, 0x02,   -1,   -1,   -1,   -1,   -1, 0x00,
        !           125:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           126:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           127:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           128:        0x05, 0x15,   -1, 0x02,   -1,   -1,   -1,   -1,
        !           129:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           130:        0x02, 0x02,   -1,   -1,   -1,   -1,   -1,   -1,
        !           131:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           132:        0x02, 0x00, 0x03, 0x03,   -1,   -1,   -1,   -1,
        !           133:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           134:        0x04, 0x04, 0x03, 0x09,   -1,   -1,   -1,   -1,
        !           135:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           136:          -1,   -1,   -1,   -1,   -1,   -1, 0x01, 0x01,
        !           137:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           138:        0x06,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           139:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           140:        0x02, 0x02,   -1,   -1,   -1,   -1,   -1,   -1,
        !           141:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           142:        0x02, 0x00, 0x00, 0x00,   -1,   -1,   -1,   -1,
        !           143:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           144:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           145:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           146:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           147:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           148:        0x02, 0x02,   -1,   -1, 0x02,   -1,   -1,   -1,
        !           149:        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           150:          -1,   -1, 0x02,   -1,   -1,   -1,   -1, 0x00,
        !           151:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           152:          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
        !           153: };
        !           154:
        !           155:
        !           156: /*
        !           157:  * Define the private functions
        !           158:  */
        !           159:
        !           160: /* for debugging */
        !           161: #ifdef ADB_DEBUG
        !           162: void   pm_printerr(char *, int, int, char *);
        !           163: #endif
        !           164:
        !           165: int    pm_wait_busy(int);
        !           166: int    pm_wait_free(int);
        !           167:
        !           168: /* these functions are for the PB Duo series and the PB 5XX series */
        !           169: int    pm_receive_pm2(u_char *);
        !           170: int    pm_send_pm2(u_char);
        !           171: int    pm_pmgrop_pm2(PMData *);
        !           172: void   pm_intr_pm2(void);
        !           173:
        !           174: /* these functions also use the variables of adb_direct.c */
        !           175: void   pm_adb_get_TALK_result(PMData *);
        !           176: void   pm_adb_get_ADB_data(PMData *);
        !           177:
        !           178:
        !           179: /*
        !           180:  * These variables are in adb_direct.c.
        !           181:  */
        !           182: extern u_char  *adbBuffer;     /* pointer to user data area */
        !           183: extern void    *adbCompRout;   /* pointer to the completion routine */
        !           184: extern void    *adbCompData;   /* pointer to the completion routine data */
        !           185: extern int     adbWaiting;     /* waiting for return data from the device */
        !           186: extern int     adbWaitingCmd;  /* ADB command we are waiting for */
        !           187: extern int     adbStarting;    /* doing ADB reinit, so do "polling" differently */
        !           188:
        !           189: #define        ADB_MAX_MSG_LENGTH      16
        !           190: #define        ADB_MAX_HDR_LENGTH      8
        !           191: struct adbCommand {
        !           192:        u_char  header[ADB_MAX_HDR_LENGTH];     /* not used yet */
        !           193:        u_char  data[ADB_MAX_MSG_LENGTH];       /* packet data only */
        !           194:        u_char  *saveBuf;       /* where to save result */
        !           195:        u_char  *compRout;      /* completion routine pointer */
        !           196:        u_char  *compData;      /* completion routine data pointer */
        !           197:        u_int   cmd;            /* the original command for this data */
        !           198:        u_int   unsol;          /* 1 if packet was unsolicited */
        !           199:        u_int   ack_only;       /* 1 for no special processing */
        !           200: };
        !           201: extern void    adb_pass_up(struct adbCommand *);
        !           202:
        !           203:
        !           204: #ifdef ADB_DEBUG
        !           205: /*
        !           206:  * This function dumps contents of the PMData
        !           207:  */
        !           208: void
        !           209: pm_printerr(ttl, rval, num, data)
        !           210:        char *ttl;
        !           211:        int rval;
        !           212:        int num;
        !           213:        char *data;
        !           214: {
        !           215:        int i;
        !           216:
        !           217:        printf("pm: %s:%04x %02x ", ttl, rval, num);
        !           218:        for (i = 0; i < num; i++)
        !           219:                printf("%02x ", data[i]);
        !           220:        printf("\n");
        !           221: }
        !           222: #endif
        !           223:
        !           224:
        !           225:
        !           226: /*
        !           227:  * Check the hardware type of the Power Manager
        !           228:  */
        !           229: void
        !           230: pm_setup_adb()
        !           231: {
        !           232:        pmHardware = PM_HW_PB5XX;       /* XXX */
        !           233: }
        !           234:
        !           235:
        !           236: /*
        !           237:  * Wait until PM IC is busy
        !           238:  */
        !           239: int
        !           240: pm_wait_busy(int delay)
        !           241: {
        !           242:        while (PM_IS_ON) {
        !           243: #ifdef PM_GRAB_SI
        !           244:                (void)intr_dispatch(0x70);
        !           245: #endif
        !           246:                if ((--delay) < 0)
        !           247:                        return 1;       /* timeout */
        !           248:        }
        !           249:        return 0;
        !           250: }
        !           251:
        !           252:
        !           253: /*
        !           254:  * Wait until PM IC is free
        !           255:  */
        !           256: int
        !           257: pm_wait_free(int delay)
        !           258: {
        !           259:        while (PM_IS_OFF) {
        !           260: #ifdef PM_GRAB_SI
        !           261:                (void)intr_dispatch(0x70);
        !           262: #endif
        !           263:                if ((--delay) < 0)
        !           264:                        return 0;       /* timeout */
        !           265:        }
        !           266:        return 1;
        !           267: }
        !           268:
        !           269: /*
        !           270:  * Functions for the PB Duo series and the PB 5XX series
        !           271:  */
        !           272:
        !           273: /*
        !           274:  * Receive data from PM for the PB Duo series and the PB 5XX series
        !           275:  */
        !           276: int
        !           277: pm_receive_pm2(u_char *data)
        !           278: {
        !           279:        int i;
        !           280:        int rval;
        !           281:
        !           282:        rval = 0xffffcd34;
        !           283:
        !           284:        switch (1) {
        !           285:        default:
        !           286:                /* set VIA SR to input mode */
        !           287:                via_reg_or(VIA1, vACR, 0x0c);
        !           288:                via_reg_and(VIA1, vACR, ~0x10);
        !           289:                i = PM_SR();
        !           290:
        !           291:                PM_SET_STATE_ACKOFF();
        !           292:                if (pm_wait_busy((int)ADBDelay*32) != 0)
        !           293:                        break;          /* timeout */
        !           294:
        !           295:                PM_SET_STATE_ACKON();
        !           296:                rval = 0xffffcd33;
        !           297:                if (pm_wait_free((int)ADBDelay*32) == 0)
        !           298:                        break;          /* timeout */
        !           299:
        !           300:                *data = PM_SR();
        !           301:                rval = 0;
        !           302:
        !           303:                break;
        !           304:        }
        !           305:
        !           306:        PM_SET_STATE_ACKON();
        !           307:        via_reg_or(VIA1, vACR, 0x1c);
        !           308:
        !           309:        return rval;
        !           310: }
        !           311:
        !           312: /*
        !           313:  * Send data to PM for the PB Duo series and the PB 5XX series
        !           314:  */
        !           315: int
        !           316: pm_send_pm2(data)
        !           317:        u_char data;
        !           318: {
        !           319:        int rval;
        !           320:
        !           321:        via_reg_or(VIA1, vACR, 0x1c);
        !           322:        write_via_reg(VIA1, vSR, data); /* PM_SR() = data; */
        !           323:
        !           324:        PM_SET_STATE_ACKOFF();
        !           325:        rval = 0xffffcd36;
        !           326:        if (pm_wait_busy((int)ADBDelay*32) != 0) {
        !           327:                PM_SET_STATE_ACKON();
        !           328:                via_reg_or(VIA1, vACR, 0x1c);
        !           329:                return rval;
        !           330:        }
        !           331:
        !           332:        PM_SET_STATE_ACKON();
        !           333:        rval = 0xffffcd35;
        !           334:        if (pm_wait_free((int)ADBDelay*32) != 0)
        !           335:                rval = 0;
        !           336:
        !           337:        PM_SET_STATE_ACKON();
        !           338:        via_reg_or(VIA1, vACR, 0x1c);
        !           339:
        !           340:        return rval;
        !           341: }
        !           342:
        !           343:
        !           344:
        !           345: /*
        !           346:  * My PMgrOp routine for the PB Duo series and the PB 5XX series
        !           347:  */
        !           348: int
        !           349: pm_pmgrop_pm2(PMData *pmdata)
        !           350: {
        !           351:        int i;
        !           352:        int s;
        !           353:        u_char via1_vIER;
        !           354:        int rval = 0;
        !           355:        int num_pm_data = 0;
        !           356:        u_char pm_cmd;
        !           357:        short pm_num_rx_data;
        !           358:        u_char pm_data;
        !           359:        u_char *pm_buf;
        !           360:
        !           361:        s = splhigh();
        !           362:
        !           363:        /* disable all interrupts but PM */
        !           364:        via1_vIER = 0x10;
        !           365:        via1_vIER &= read_via_reg(VIA1, vIER);
        !           366:        write_via_reg(VIA1, vIER, via1_vIER);
        !           367:        if (via1_vIER != 0x0)
        !           368:                via1_vIER |= 0x80;
        !           369:
        !           370:        switch (pmdata->command) {
        !           371:        default:
        !           372:                /* wait until PM is free */
        !           373:                pm_cmd = (u_char)(pmdata->command & 0xff);
        !           374:                rval = 0xcd38;
        !           375:                if (pm_wait_free(ADBDelay * 4) == 0)
        !           376:                        break;                  /* timeout */
        !           377:
        !           378:                /* send PM command */
        !           379:                if ((rval = pm_send_pm2((u_char)(pm_cmd & 0xff))))
        !           380:                        break;                          /* timeout */
        !           381:
        !           382:                /* send number of PM data */
        !           383:                num_pm_data = pmdata->num_data;
        !           384:                if (pm_send_cmd_type[pm_cmd] < 0) {
        !           385:                        if ((rval = pm_send_pm2((u_char)(num_pm_data & 0xff))) != 0)
        !           386:                                break;          /* timeout */
        !           387:                        pmdata->command = 0;
        !           388:                }
        !           389:                /* send PM data */
        !           390:                pm_buf = (u_char *)pmdata->s_buf;
        !           391:                for (i = 0 ; i < num_pm_data; i++)
        !           392:                        if ((rval = pm_send_pm2(pm_buf[i])) != 0)
        !           393:                                break;                  /* timeout */
        !           394:                if (i != num_pm_data)
        !           395:                        break;                          /* timeout */
        !           396:
        !           397:
        !           398:                /* check if PM will send me data  */
        !           399:                pm_num_rx_data = pm_receive_cmd_type[pm_cmd];
        !           400:                pmdata->num_data = pm_num_rx_data;
        !           401:                if (pm_num_rx_data == 0) {
        !           402:                        rval = 0;
        !           403:                        break;                          /* no return data */
        !           404:                }
        !           405:
        !           406:                /* receive PM command */
        !           407:                pm_data = pmdata->command;
        !           408:                pm_num_rx_data--;
        !           409:                if (pm_num_rx_data == 0)
        !           410:                        if ((rval = pm_receive_pm2(&pm_data)) != 0) {
        !           411:                                rval = 0xffffcd37;
        !           412:                                break;
        !           413:                        }
        !           414:                pmdata->command = pm_data;
        !           415:
        !           416:                /* receive number of PM data */
        !           417:                if (pm_num_rx_data < 0) {
        !           418:                        if ((rval = pm_receive_pm2(&pm_data)) != 0)
        !           419:                                break;          /* timeout */
        !           420:                        num_pm_data = pm_data;
        !           421:                } else
        !           422:                        num_pm_data = pm_num_rx_data;
        !           423:                pmdata->num_data = num_pm_data;
        !           424:
        !           425:                /* receive PM data */
        !           426:                pm_buf = (u_char *)pmdata->r_buf;
        !           427:                for (i = 0; i < num_pm_data; i++) {
        !           428:                        if ((rval = pm_receive_pm2(&pm_data)) != 0)
        !           429:                                break;                  /* timeout */
        !           430:                        pm_buf[i] = pm_data;
        !           431:                }
        !           432:
        !           433:                rval = 0;
        !           434:        }
        !           435:
        !           436:        /* restore former value */
        !           437:        write_via_reg(VIA1, vIER, via1_vIER);
        !           438:        splx(s);
        !           439:
        !           440:        return rval;
        !           441: }
        !           442:
        !           443:
        !           444: /*
        !           445:  * My PM interrupt routine for the PB Duo series and the PB 5XX series
        !           446:  */
        !           447: void
        !           448: pm_intr_pm2()
        !           449: {
        !           450:        int s;
        !           451:        int rval;
        !           452:        PMData pmdata;
        !           453:
        !           454:        s = splhigh();
        !           455:
        !           456:        PM_VIA_CLR_INTR();                      /* clear VIA1 interrupt */
        !           457:                                                /* ask PM what happend */
        !           458:        pmdata.command = 0x78;
        !           459:        pmdata.num_data = 0;
        !           460:        pmdata.s_buf = &pmdata.data[2];
        !           461:        pmdata.r_buf = &pmdata.data[2];
        !           462:        rval = pm_pmgrop_pm2(&pmdata);
        !           463:        if (rval != 0) {
        !           464: #ifdef ADB_DEBUG
        !           465:                if (adb_debug)
        !           466:                        printf("pm: PM is not ready. error code: %08x\n", rval);
        !           467: #endif
        !           468:                splx(s);
        !           469:                return;
        !           470:        }
        !           471:
        !           472:        switch ((u_int)(pmdata.data[2] & 0xff)) {
        !           473:        case 0x00:              /* 1 sec interrupt? */
        !           474:                break;
        !           475:        case PMU_INT_TICK:      /* 1 sec interrupt? */
        !           476:                break;
        !           477:        case PMU_INT_SNDBRT:    /* Brightness/Contrast button on LCD panel */
        !           478:                break;
        !           479:        case PMU_INT_ADB:       /* ADB data requested by TALK command */
        !           480:        case PMU_INT_ADB|PMU_INT_ADB_AUTO:
        !           481:                pm_adb_get_TALK_result(&pmdata);
        !           482:                break;
        !           483:        case 0x16:              /* ADB device event */
        !           484:        case 0x18:
        !           485:        case 0x1e:
        !           486:        case PMU_INT_WAKEUP:
        !           487:                pm_adb_get_ADB_data(&pmdata);
        !           488:                break;
        !           489:        default:
        !           490: #ifdef ADB_DEBUG
        !           491:                if (adb_debug)
        !           492:                        pm_printerr("driver does not support this event.",
        !           493:                            pmdata.data[2], pmdata.num_data,
        !           494:                            pmdata.data);
        !           495: #endif
        !           496:                break;
        !           497:        }
        !           498:
        !           499:        splx(s);
        !           500: }
        !           501:
        !           502:
        !           503: /*
        !           504:  * My PMgrOp routine
        !           505:  */
        !           506: int
        !           507: pmgrop(PMData *pmdata)
        !           508: {
        !           509:        switch (pmHardware) {
        !           510:        case PM_HW_PB5XX:
        !           511:                return (pm_pmgrop_pm2(pmdata));
        !           512:        default:
        !           513:                /* return (pmgrop_mrg(pmdata)); */
        !           514:                return 1;
        !           515:        }
        !           516: }
        !           517:
        !           518:
        !           519: /*
        !           520:  * My PM interrupt routine
        !           521:  */
        !           522: void
        !           523: pm_intr()
        !           524: {
        !           525:        switch (pmHardware) {
        !           526:        case PM_HW_PB5XX:
        !           527:                pm_intr_pm2();
        !           528:                break;
        !           529:        default:
        !           530:                break;
        !           531:        }
        !           532: }
        !           533:
        !           534:
        !           535:
        !           536: /*
        !           537:  * Synchronous ADBOp routine for the Power Manager
        !           538:  */
        !           539: int
        !           540: pm_adb_op(u_char *buffer, void *compRout, void *data, int command)
        !           541: {
        !           542:        int i;
        !           543:        int s;
        !           544:        int rval;
        !           545:        int ndelay;
        !           546:        int waitfor;    /* interrupts to poll for */
        !           547:        int ifr;
        !           548: #ifdef ADB_DEBUG
        !           549:        int oldifr;
        !           550: #endif
        !           551:        PMData pmdata;
        !           552:        struct adbCommand packet;
        !           553:        extern int adbempty;
        !           554:
        !           555:        if (adbWaiting == 1)
        !           556:                return 1;
        !           557:
        !           558:        s = splhigh();
        !           559:        write_via_reg(VIA1, vIER, 0x10);
        !           560:
        !           561:        adbBuffer = buffer;
        !           562:        adbCompRout = compRout;
        !           563:        adbCompData = data;
        !           564:
        !           565:        pmdata.command = 0x20;
        !           566:        pmdata.s_buf = pmdata.data;
        !           567:        pmdata.r_buf = pmdata.data;
        !           568:
        !           569:        /*
        !           570:         * if the command is LISTEN,
        !           571:         * add number of ADB data to number of PM data
        !           572:         */
        !           573:        if ((command & 0xc) == 0x8) {
        !           574:                if (buffer != (u_char *)0)
        !           575:                        pmdata.num_data = buffer[0] + 3;
        !           576:        } else
        !           577:                pmdata.num_data = 3;
        !           578:
        !           579:        /*
        !           580:         * Resetting adb on several models, such as
        !           581:         * - PowerBook3,*
        !           582:         * - PowerBook5,*
        !           583:         * - PowerMac10,1
        !           584:         * causes several pmu interrupts with ifr set to PMU_INT_SNDBRT.
        !           585:         * Not processing them prevents us from seeing the adb devices
        !           586:         * afterwards, so we have to expect it unless we know the adb
        !           587:         * bus is empty.
        !           588:         */
        !           589:        if (command == PMU_RESET_ADB) {
        !           590:                waitfor = PMU_INT_ADB_AUTO | PMU_INT_ADB;
        !           591:                if (adbempty == 0)
        !           592:                        waitfor |= PMU_INT_SNDBRT;
        !           593:        } else
        !           594:                waitfor = PMU_INT_ALL;
        !           595:
        !           596:        pmdata.data[0] = (u_char)(command & 0xff);
        !           597:        pmdata.data[1] = 0;
        !           598:        /* if the command is LISTEN, copy ADB data to PM buffer */
        !           599:        if ((command & 0xc) == 0x8) {
        !           600:                if ((buffer != (u_char *)0) && (buffer[0] <= 24)) {
        !           601:                        pmdata.data[2] = buffer[0];     /* number of data */
        !           602:                        for (i = 0; i < buffer[0]; i++)
        !           603:                                pmdata.data[3 + i] = buffer[1 + i];
        !           604:                } else
        !           605:                        pmdata.data[2] = 0;
        !           606:        } else
        !           607:                pmdata.data[2] = 0;
        !           608:
        !           609:        if ((command & 0xc) != 0xc) {   /* if the command is not TALK */
        !           610:                /* set up stuff for adb_pass_up */
        !           611:                packet.data[0] = 1 + pmdata.data[2];
        !           612:                packet.data[1] = command;
        !           613:                for (i = 0; i < pmdata.data[2]; i++)
        !           614:                        packet.data[i+2] = pmdata.data[i+3];
        !           615:                packet.saveBuf = adbBuffer;
        !           616:                packet.compRout = adbCompRout;
        !           617:                packet.compData = adbCompData;
        !           618:                packet.cmd = command;
        !           619:                packet.unsol = 0;
        !           620:                packet.ack_only = 1;
        !           621:                adb_polling = 1;
        !           622:                adb_pass_up(&packet);
        !           623:                adb_polling = 0;
        !           624:        }
        !           625:
        !           626:        rval = pmgrop(&pmdata);
        !           627:        if (rval != 0) {
        !           628:                splx(s);
        !           629:                return 1;
        !           630:        }
        !           631:
        !           632:        delay (1000);
        !           633:
        !           634:        adbWaiting = 1;
        !           635:        adbWaitingCmd = command;
        !           636:
        !           637:        PM_VIA_INTR_ENABLE();
        !           638:
        !           639:        /* wait until the PM interrupt is occurred */
        !           640:        ndelay = 0x8000;
        !           641: #ifdef ADB_DEBUG
        !           642:        oldifr = 0;
        !           643: #endif
        !           644:        while (adbWaiting == 1) {
        !           645:                ifr = read_via_reg(VIA1, vIFR);
        !           646:                if (ifr & waitfor) {
        !           647:                        pm_intr();
        !           648: #ifdef PM_GRAB_SI
        !           649:                        (void)intr_dispatch(0x70);
        !           650: #endif
        !           651: #ifdef ADB_DEBUG
        !           652:                } else if (ifr != oldifr) {
        !           653:                        if (adb_debug)
        !           654:                                printf("pm_adb_op: ignoring ifr %02x"
        !           655:                                    ", expecting %02x\n",
        !           656:                                    (u_int)ifr, (u_int)waitfor);
        !           657:                        oldifr = ifr;
        !           658: #endif
        !           659:                }
        !           660:                if ((--ndelay) < 0) {
        !           661:                        splx(s);
        !           662:                        return 1;
        !           663:                }
        !           664:                delay(10);
        !           665:        }
        !           666:
        !           667:        /* this command enables the interrupt by operating ADB devices */
        !           668:        pmdata.command = 0x20;
        !           669:        pmdata.num_data = 4;
        !           670:        pmdata.s_buf = pmdata.data;
        !           671:        pmdata.r_buf = pmdata.data;
        !           672:        pmdata.data[0] = 0x00;
        !           673:        pmdata.data[1] = 0x86;  /* magic spell for awaking the PM */
        !           674:        pmdata.data[2] = 0x00;
        !           675:        pmdata.data[3] = 0x0c;  /* each bit may express the existent ADB device */
        !           676:        rval = pmgrop(&pmdata);
        !           677:
        !           678:        splx(s);
        !           679:        return rval;
        !           680: }
        !           681:
        !           682:
        !           683: void
        !           684: pm_adb_get_TALK_result(PMData *pmdata)
        !           685: {
        !           686:        int i;
        !           687:        struct adbCommand packet;
        !           688:
        !           689:        /* set up data for adb_pass_up */
        !           690:        packet.data[0] = pmdata->num_data-1;
        !           691:        packet.data[1] = pmdata->data[3];
        !           692:        for (i = 0; i <packet.data[0]-1; i++)
        !           693:                packet.data[i+2] = pmdata->data[i+4];
        !           694:
        !           695:        packet.saveBuf = adbBuffer;
        !           696:        packet.compRout = adbCompRout;
        !           697:        packet.compData = adbCompData;
        !           698:        packet.unsol = 0;
        !           699:        packet.ack_only = 0;
        !           700:        adb_polling = 1;
        !           701:        adb_pass_up(&packet);
        !           702:        adb_polling = 0;
        !           703:
        !           704:        adbWaiting = 0;
        !           705:        adbBuffer = (long)0;
        !           706:        adbCompRout = (long)0;
        !           707:        adbCompData = (long)0;
        !           708: }
        !           709:
        !           710:
        !           711: void
        !           712: pm_adb_get_ADB_data(PMData *pmdata)
        !           713: {
        !           714:        int i;
        !           715:        struct adbCommand packet;
        !           716:
        !           717:        /* set up data for adb_pass_up */
        !           718:        packet.data[0] = pmdata->num_data-1;    /* number of raw data */
        !           719:        packet.data[1] = pmdata->data[3];       /* ADB command */
        !           720:        for (i = 0; i <packet.data[0]-1; i++)
        !           721:                packet.data[i+2] = pmdata->data[i+4];
        !           722:        packet.unsol = 1;
        !           723:        packet.ack_only = 0;
        !           724:        adb_pass_up(&packet);
        !           725: }
        !           726:
        !           727: void
        !           728: pm_adb_restart()
        !           729: {
        !           730:        PMData p;
        !           731:
        !           732:        p.command = PMU_RESET_CPU;
        !           733:        p.num_data = 0;
        !           734:        p.s_buf = p.data;
        !           735:        p.r_buf = p.data;
        !           736:        pmgrop(&p);
        !           737: }
        !           738:
        !           739: void
        !           740: pm_adb_poweroff()
        !           741: {
        !           742:        PMData p;
        !           743:
        !           744:        bzero(&p, sizeof p);
        !           745:        p.command = PMU_POWER_OFF;
        !           746:        p.num_data = 4;
        !           747:        p.s_buf = p.data;
        !           748:        p.r_buf = p.data;
        !           749:        strlcpy(p.data, "MATT", sizeof p.data);
        !           750:        pmgrop(&p);
        !           751: }
        !           752:
        !           753: void
        !           754: pm_read_date_time(time_t *time)
        !           755: {
        !           756:        PMData p;
        !           757:
        !           758:        p.command = PMU_READ_RTC;
        !           759:        p.num_data = 0;
        !           760:        p.s_buf = p.data;
        !           761:        p.r_buf = p.data;
        !           762:        pmgrop(&p);
        !           763:
        !           764:        bcopy(p.data, time, 4);
        !           765: }
        !           766:
        !           767: void
        !           768: pm_set_date_time(time_t time)
        !           769: {
        !           770:        PMData p;
        !           771:
        !           772:        p.command = PMU_SET_RTC;
        !           773:        p.num_data = 4;
        !           774:        p.s_buf = p.r_buf = p.data;
        !           775:        bcopy(&time, p.data, 4);
        !           776:        pmgrop(&p);
        !           777: }
        !           778:
        !           779: #if 0
        !           780: void
        !           781: pm_eject_pcmcia(int slot)
        !           782: {
        !           783:        PMData p;
        !           784:
        !           785:        if (slot != 0 && slot != 1)
        !           786:                return;
        !           787:
        !           788:        p.command = PMU_EJECT_PCMCIA;
        !           789:        p.num_data = 1;
        !           790:        p.s_buf = p.r_buf = p.data;
        !           791:        p.data[0] = 5 + slot;   /* XXX */
        !           792:        pmgrop(&p);
        !           793: }
        !           794: #endif
        !           795:
        !           796:
        !           797: /*
        !           798:  * Thanks to Paul Mackerras and Fabio Riccardi's Linux implementation
        !           799:  * for a clear description of the PMU results.
        !           800:  */
        !           801:
        !           802: int
        !           803: pm_battery_info(int battery, struct pmu_battery_info *info)
        !           804: {
        !           805:        PMData p;
        !           806:
        !           807:        p.command = PMU_SMART_BATTERY_STATE;
        !           808:        p.num_data = 1;
        !           809:        p.s_buf = p.r_buf = p.data;
        !           810:        p.data[0] = battery + 1;
        !           811:        pmgrop(&p);
        !           812:
        !           813:        info->flags = p.data[1];
        !           814:
        !           815:        switch (p.data[0]) {
        !           816:        case 3:
        !           817:        case 4:
        !           818:                info->cur_charge = p.data[2];
        !           819:                info->max_charge = p.data[3];
        !           820:                info->draw = *((signed char *)&p.data[4]);
        !           821:                info->voltage = p.data[5];
        !           822:                break;
        !           823:        case 5:
        !           824:                info->cur_charge = ((p.data[2] << 8) | (p.data[3]));
        !           825:                info->max_charge = ((p.data[4] << 8) | (p.data[5]));
        !           826:                info->draw = *((signed short *)&p.data[6]);
        !           827:                info->voltage = ((p.data[8] << 8) | (p.data[7]));
        !           828:                break;
        !           829:        default:
        !           830:                /* XXX - Error condition */
        !           831:                info->cur_charge = 0;
        !           832:                info->max_charge = 0;
        !           833:                info->draw = 0;
        !           834:                info->voltage = 0;
        !           835:                break;
        !           836:        }
        !           837:
        !           838:        return 1;
        !           839: }
        !           840:
        !           841: void
        !           842: pmu_fileserver_mode(int on)
        !           843: {
        !           844:        PMData p;
        !           845:
        !           846:        p.command = PMU_POWER_EVENTS;
        !           847:        p.num_data = 1;
        !           848:        p.s_buf = p.r_buf = p.data;
        !           849:        p.data[0] = PMU_PWR_GET_POWERUP_EVENTS;
        !           850:        pmgrop(&p);
        !           851:
        !           852:        p.command = PMU_POWER_EVENTS;
        !           853:        p.num_data = 3;
        !           854:        p.s_buf = p.r_buf = p.data;
        !           855:        p.data[1] = p.data[0];   /* result from the get */
        !           856:        if (on) {
        !           857:                p.data[0] = PMU_PWR_SET_POWERUP_EVENTS;
        !           858:                p.data[2] = PMU_WAKE_AC_LOSS;
        !           859:        } else {
        !           860:                p.data[0] = PMU_PWR_CLR_POWERUP_EVENTS;
        !           861:                p.data[2] = PMU_WAKE_AC_LOSS;
        !           862:        }
        !           863:        pmgrop(&p);
        !           864: }

CVSweb