[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

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