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

Annotation of sys/arch/mac68k/dev/pm_direct.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: pm_direct.c,v 1.13 2007/03/17 20:01:44 miod Exp $     */
                      2: /*     $NetBSD: pm_direct.c,v 1.25 2005/10/28 21:54:52 christos 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: /* From: pm_direct.c 1.3 03/18/98 Takashi Hamada */
                     34:
                     35: #ifdef DEBUG
                     36: #ifndef ADB_DEBUG
                     37: #define ADB_DEBUG
                     38: #endif
                     39: #endif
                     40:
                     41: /* #define     PM_GRAB_SI      1 */
                     42:
                     43: #include <sys/param.h>
                     44: #include <sys/systm.h>
                     45: #include <sys/device.h>
                     46:
                     47: #include <machine/cpu.h>
                     48: #include <machine/viareg.h>
                     49:
                     50: #include <dev/adb/adb.h>
                     51: #include <mac68k/dev/adbvar.h>
                     52: #include <mac68k/dev/pm_direct.h>
                     53:
                     54: /* hardware dependent values */
                     55: u_int32_t HwCfgFlags3;
                     56: u_short ADBDelay = 0xcea;
                     57:
                     58: /* define the types of the Power Manager */
                     59: #define PM_HW_UNKNOWN          0x00    /* don't know */
                     60: #define PM_HW_PB1XX            0x01    /* PowerBook 1XX series */
                     61: #define        PM_HW_PB5XX             0x02    /* PowerBook Duo and 5XX series */
                     62:
                     63: /* useful macros */
                     64: #define PM_SR()                        via_reg(VIA1, vSR)
                     65: #define PM_VIA_INTR_ENABLE()   via_reg(VIA1, vIER) = 0x90
                     66: #define PM_VIA_INTR_DISABLE()  via_reg(VIA1, vIER) = 0x10
                     67: #define PM_VIA_CLR_INTR()      via_reg(VIA1, vIFR) = 0x90
                     68: #define PM_SET_STATE_ACKON()   via_reg(VIA2, vBufB) |= 0x04
                     69: #define PM_SET_STATE_ACKOFF()  via_reg(VIA2, vBufB) &= ~0x04
                     70: #define PM_IS_ON               (0x02 == (via_reg(VIA2, vBufB) & 0x02))
                     71: #define PM_IS_OFF              (0x00 == (via_reg(VIA2, vBufB) & 0x02))
                     72:
                     73: /*
                     74:  * Variables for internal use
                     75:  */
                     76: int    pmHardware = PM_HW_UNKNOWN;
                     77: u_short        pm_existent_ADB_devices = 0x0;  /* each bit expresses the existent ADB device */
                     78: u_int  pm_LCD_brightness = 0x0;
                     79: u_int  pm_LCD_contrast = 0x0;
                     80: u_int  pm_counter = 0;                 /* clock count */
                     81:
                     82: /* these values shows that number of data returned after 'send' cmd is sent */
                     83: char pm_send_cmd_type[] = {
                     84:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                     85:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                     86:        0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                     87:        0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
                     88:        0xff, 0x00, 0x02, 0x01, 0x01, 0xff, 0xff, 0xff,
                     89:        0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                     90:        0x04, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                     91:        0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff,
                     92:        0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                     93:        0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                     94:        0x01, 0x00, 0x02, 0x02, 0xff, 0x01, 0x03, 0x01,
                     95:        0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
                     96:        0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                     97:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
                     98:        0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
                     99:        0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x04, 0x04,
                    100:        0x04, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
                    101:        0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    102:        0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    103:        0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    104:        0x02, 0x02, 0x02, 0x04, 0xff, 0x00, 0xff, 0xff,
                    105:        0x01, 0x01, 0x03, 0x02, 0xff, 0xff, 0xff, 0xff,
                    106:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    107:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    108:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    109:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    110:        0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    111:        0x01, 0x01, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
                    112:        0xff, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
                    113:        0x03, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
                    114:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    115:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
                    116: };
                    117:
                    118: /* these values shows that number of data returned after 'receive' cmd is sent */
                    119: char pm_receive_cmd_type[] = {
                    120:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    121:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    122:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    123:        0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
                    124:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    125:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    126:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    127:        0x05, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    128:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    129:        0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    130:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    131:        0x02, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff,
                    132:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    133:        0x04, 0x04, 0x03, 0x09, 0xff, 0xff, 0xff, 0xff,
                    134:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    135:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01,
                    136:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    137:        0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    138:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    139:        0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    140:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    141:        0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
                    142:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    143:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    144:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    145:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    146:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    147:        0x02, 0x02, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff,
                    148:        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                    149:        0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00,
                    150:        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    151:        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                    152: };
                    153:
                    154:
                    155: /*
                    156:  * Define the private functions
                    157:  */
                    158:
                    159: /* for debugging */
                    160: #ifdef ADB_DEBUG
                    161: void   pm_printerr(const char *, int, int, char *);
                    162: #endif
                    163:
                    164: int    pm_wait_busy(int);
                    165: int    pm_wait_free(int);
                    166:
                    167: /* these functions are for the PB1XX series */
                    168: int    pm_receive_pm1(u_char *);
                    169: int    pm_send_pm1(u_char, int);
                    170: int    pm_pmgrop_pm1(PMData *);
                    171: int    pm_intr_pm1(void *);
                    172:
                    173: /* these functions are for the PB Duo series and the PB 5XX series */
                    174: int    pm_receive_pm2(u_char *);
                    175: int    pm_send_pm2(u_char);
                    176: int    pm_pmgrop_pm2(PMData *);
                    177: int    pm_intr_pm2(void *);
                    178:
                    179: /* these functions are called from adb_direct.c */
                    180: void   pm_setup_adb(void);
                    181: void   pm_check_adb_devices(int);
                    182: int    pm_intr(void *);
                    183: int    pm_adb_op(u_char *, void *, void *, int);
                    184: void   pm_hw_setup(struct device *);
                    185:
                    186: /* these functions also use the variables of adb_direct.c */
                    187: void   pm_adb_get_TALK_result(PMData *);
                    188: void   pm_adb_get_ADB_data(PMData *);
                    189: void   pm_adb_poll_next_device_pm1(PMData *);
                    190:
                    191:
                    192: /*
                    193:  * These variables are in adb_direct.c.
                    194:  */
                    195: extern u_char  *adbBuffer;     /* pointer to user data area */
                    196: extern void    *adbCompRout;   /* pointer to the completion routine */
                    197: extern void    *adbCompData;   /* pointer to the completion routine data */
                    198: extern int     adbWaiting;     /* waiting for return data from the device */
                    199: extern int     adbWaitingCmd;  /* ADB command we are waiting for */
                    200: extern int     adbStarting;    /* doing ADB reinit, so do "polling" differently */
                    201:
                    202: #define        ADB_MAX_MSG_LENGTH      16
                    203: #define        ADB_MAX_HDR_LENGTH      8
                    204: struct adbCommand {
                    205:        u_char  header[ADB_MAX_HDR_LENGTH];     /* not used yet */
                    206:        u_char  data[ADB_MAX_MSG_LENGTH];       /* packet data only */
                    207:        u_char  *saveBuf;       /* where to save result */
                    208:        u_char  *compRout;      /* completion routine pointer */
                    209:        u_char  *compData;      /* completion routine data pointer */
                    210:        u_int   cmd;            /* the original command for this data */
                    211:        u_int   unsol;          /* 1 if packet was unsolicited */
                    212:        u_int   ack_only;       /* 1 for no special processing */
                    213: };
                    214: extern void    adb_pass_up(struct adbCommand *);
                    215:
                    216: #ifdef ADB_DEBUG
                    217: /*
                    218:  * This function dumps contents of the PMData
                    219:  */
                    220: void
                    221: pm_printerr(const char *ttl, int rval, int num, char *data)
                    222: {
                    223:        int i;
                    224:
                    225:        printf("pm: %s:%04x %02x ", ttl, rval, num);
                    226:        for (i = 0; i < num; i++)
                    227:                printf("%02x ", data[i]);
                    228:        printf("\n");
                    229: }
                    230: #endif
                    231:
                    232:
                    233:
                    234: /*
                    235:  * Check the hardware type of the Power Manager
                    236:  */
                    237: void
                    238: pm_setup_adb(void)
                    239: {
                    240:        switch (mac68k_machine.machineid) {
                    241:        case MACH_MACPB140:
                    242:        case MACH_MACPB145:
                    243:        case MACH_MACPB160:
                    244:        case MACH_MACPB165:
                    245:        case MACH_MACPB165C:
                    246:        case MACH_MACPB170:
                    247:        case MACH_MACPB180:
                    248:        case MACH_MACPB180C:
                    249:                pmHardware = PM_HW_PB1XX;
                    250:                break;
                    251:        case MACH_MACPB150:
                    252:        case MACH_MACPB210:
                    253:        case MACH_MACPB230:
                    254:        case MACH_MACPB250:
                    255:        case MACH_MACPB270:
                    256:        case MACH_MACPB280:
                    257:        case MACH_MACPB280C:
                    258:        case MACH_MACPB500:
                    259:        case MACH_MACPB190:
                    260:        case MACH_MACPB190CS:
                    261:                pmHardware = PM_HW_PB5XX;
                    262:                break;
                    263:        default:
                    264:                break;
                    265:        }
                    266: }
                    267:
                    268:
                    269: /*
                    270:  * Check the existent ADB devices
                    271:  */
                    272: void
                    273: pm_check_adb_devices(int id)
                    274: {
                    275:        u_short ed = 0x1;
                    276:
                    277:        ed <<= id;
                    278:        pm_existent_ADB_devices |= ed;
                    279: }
                    280:
                    281:
                    282: /*
                    283:  * Wait until PM IC is busy
                    284:  */
                    285: int
                    286: pm_wait_busy(int xdelay)
                    287: {
                    288:        while (PM_IS_ON) {
                    289: #ifdef PM_GRAB_SI
                    290:                (void)intr_dispatch(0x70);      /* grab any serial interrupts */
                    291: #endif
                    292:                if ((--xdelay) < 0)
                    293:                        return 1;       /* timeout */
                    294:        }
                    295:        return 0;
                    296: }
                    297:
                    298:
                    299: /*
                    300:  * Wait until PM IC is free
                    301:  */
                    302: int
                    303: pm_wait_free(int xdelay)
                    304: {
                    305:        while (PM_IS_OFF) {
                    306: #ifdef PM_GRAB_SI
                    307:                (void)intr_dispatch(0x70);      /* grab any serial interrupts */
                    308: #endif
                    309:                if ((--xdelay) < 0)
                    310:                        return 0;       /* timeout */
                    311:        }
                    312:        return 1;
                    313: }
                    314:
                    315:
                    316:
                    317: /*
                    318:  * Functions for the PB1XX series
                    319:  */
                    320:
                    321: /*
                    322:  * Receive data from PM for the PB1XX series
                    323:  */
                    324: int
                    325: pm_receive_pm1(u_char *data)
                    326: {
                    327:        int rval = 0xffffcd34;
                    328:
                    329:        via_reg(VIA2, vDirA) = 0x00;
                    330:
                    331:        switch (1) {
                    332:        default:
                    333:                if (pm_wait_busy(0x40) != 0)
                    334:                        break;                  /* timeout */
                    335:
                    336:                PM_SET_STATE_ACKOFF();
                    337:                *data = via_reg(VIA2, 0x200);
                    338:
                    339:                rval = 0xffffcd33;
                    340:                if (pm_wait_free(0x40) == 0)
                    341:                        break;                  /* timeout */
                    342:
                    343:                rval = 0x00;
                    344:                break;
                    345:        }
                    346:
                    347:        PM_SET_STATE_ACKON();
                    348:        via_reg(VIA2, vDirA) = 0x00;
                    349:
                    350:        return rval;
                    351: }
                    352:
                    353:
                    354:
                    355: /*
                    356:  * Send data to PM for the PB1XX series
                    357:  */
                    358: int
                    359: pm_send_pm1(u_char data, int timo)
                    360: {
                    361:        int rval;
                    362:
                    363:        via_reg(VIA2, vDirA) = 0xff;
                    364:        via_reg(VIA2, 0x200) = data;
                    365:
                    366:        PM_SET_STATE_ACKOFF();
                    367: #if 0
                    368:        if (pm_wait_busy(0x400) == 0) {
                    369: #else
                    370:        if (pm_wait_busy(timo) == 0) {
                    371: #endif
                    372:                PM_SET_STATE_ACKON();
                    373:                if (pm_wait_free(0x40) != 0)
                    374:                        rval = 0x0;
                    375:                else
                    376:                        rval = 0xffffcd35;
                    377:        } else {
                    378:                rval = 0xffffcd36;
                    379:        }
                    380:
                    381:        PM_SET_STATE_ACKON();
                    382:        via_reg(VIA2, vDirA) = 0x00;
                    383:
                    384:        return rval;
                    385: }
                    386:
                    387:
                    388: /*
                    389:  * My PMgrOp routine for the PB1XX series
                    390:  */
                    391: int
                    392: pm_pmgrop_pm1(PMData *pmdata)
                    393: {
                    394:        int i;
                    395:        int s = 0x81815963;
                    396:        u_char via1_vIER, via1_vDirA;
                    397:        int rval = 0;
                    398:        int num_pm_data = 0;
                    399:        u_char pm_cmd;
                    400:        u_char pm_data;
                    401:        u_char *pm_buf;
                    402:
                    403:        /* disable all inetrrupts but PM */
                    404:        via1_vIER = via_reg(VIA1, vIER);
                    405:        PM_VIA_INTR_DISABLE();
                    406:
                    407:        via1_vDirA = via_reg(VIA1, vDirA);
                    408:
                    409:        switch (pmdata->command) {
                    410:        default:
                    411:                for (i = 0; i < 7; i++) {
                    412:                        via_reg(VIA2, vDirA) = 0x00;
                    413:
                    414:                        /* wait until PM is free */
                    415:                        if (pm_wait_free(ADBDelay) == 0) {      /* timeout */
                    416:                                via_reg(VIA2, vDirA) = 0x00;
                    417:                                /* restore former value */
                    418:                                via_reg(VIA1, vDirA) = via1_vDirA;
                    419:                                via_reg(VIA1, vIER) = via1_vIER;
                    420:                                return 0xffffcd38;
                    421:                        }
                    422:
                    423:                        switch (mac68k_machine.machineid) {
                    424:                        /* XXX what about 140 and 145? -- miod */
                    425:                        case MACH_MACPB160:
                    426:                        case MACH_MACPB165:
                    427:                        case MACH_MACPB165C:
                    428:                        case MACH_MACPB170:
                    429:                        case MACH_MACPB180:
                    430:                        case MACH_MACPB180C:
                    431:                        {
                    432:                                int xdelay = ADBDelay * 16;
                    433:
                    434:                                via_reg(VIA2, vDirA) = 0x00;
                    435:                                while ((via_reg(VIA2, 0x200) == 0x7f) && (xdelay >= 0))
                    436:                                        xdelay--;
                    437:
                    438:                                if (xdelay < 0) {       /* timeout */
                    439:                                        via_reg(VIA2, vDirA) = 0x00;
                    440:                                        /* restore former value */
                    441:                                        via_reg(VIA1, vIER) = via1_vIER;
                    442:                                        return 0xffffcd38;
                    443:                                }
                    444:                        }
                    445:                                break;
                    446:                        } /* end switch */
                    447:
                    448:                        s = splhigh();
                    449:
                    450:                        via1_vDirA = via_reg(VIA1, vDirA);
                    451:                        via_reg(VIA1, vDirA) &= 0x7f;
                    452:
                    453:                        pm_cmd = (u_char)(pmdata->command & 0xff);
                    454:                        if ((rval = pm_send_pm1(pm_cmd, ADBDelay * 8)) == 0)
                    455:                                break;  /* send command succeeded */
                    456:
                    457:                        via_reg(VIA1, vDirA) = via1_vDirA;
                    458:                        splx(s);
                    459:                } /* end for */
                    460:
                    461:                /* failed to send a command */
                    462:                if (i == 7) {
                    463:                        via_reg(VIA2, vDirA) = 0x00;
                    464:                        /* restore former value */
                    465:                        via_reg(VIA1, vDirA) = via1_vDirA;
                    466:                        via_reg(VIA1, vIER) = via1_vIER;
                    467:                        if (s != 0x81815963)
                    468:                                splx(s);
                    469:                        return 0xffffcd38;
                    470:                }
                    471:
                    472:                /* send # of PM data */
                    473:                num_pm_data = pmdata->num_data;
                    474:                if ((rval = pm_send_pm1((u_char)(num_pm_data & 0xff), ADBDelay * 8)) != 0)
                    475:                        break;                  /* timeout */
                    476:
                    477:                /* send PM data */
                    478:                pm_buf = (u_char *)pmdata->s_buf;
                    479:                for (i = 0; i < num_pm_data; i++)
                    480:                        if ((rval = pm_send_pm1(pm_buf[i], ADBDelay * 8)) != 0)
                    481:                                break;          /* timeout */
                    482:                if ((i != num_pm_data) && (num_pm_data != 0))
                    483:                        break;                  /* timeout */
                    484:
                    485:                /* Will PM IC return data? */
                    486:                if ((pm_cmd & 0x08) == 0) {
                    487:                        rval = 0;
                    488:                        break;                  /* no returned data */
                    489:                }
                    490:
                    491:                rval = 0xffffcd37;
                    492:                if (pm_wait_busy(ADBDelay) != 0)
                    493:                        break;                  /* timeout */
                    494:
                    495:                /* receive PM command */
                    496:                if ((rval = pm_receive_pm1(&pm_data)) != 0)
                    497:                        break;
                    498:
                    499:                pmdata->command = pm_data;
                    500:
                    501:                /* receive number of PM data */
                    502:                if ((rval = pm_receive_pm1(&pm_data)) != 0)
                    503:                        break;                  /* timeout */
                    504:                num_pm_data = pm_data;
                    505:                pmdata->num_data = num_pm_data;
                    506:
                    507:                /* receive PM data */
                    508:                pm_buf = (u_char *)pmdata->r_buf;
                    509:                for (i = 0; i < num_pm_data; i++) {
                    510:                        if ((rval = pm_receive_pm1(&pm_data)) != 0)
                    511:                                break;          /* timeout */
                    512:                        pm_buf[i] = pm_data;
                    513:                }
                    514:
                    515:                rval = 0;
                    516:        }
                    517:
                    518:        via_reg(VIA2, vDirA) = 0x00;
                    519:
                    520:        /* restore former value */
                    521:        via_reg(VIA1, vDirA) = via1_vDirA;
                    522:        via_reg(VIA1, vIER) = via1_vIER;
                    523:        if (s != 0x81815963)
                    524:                splx(s);
                    525:
                    526:        return rval;
                    527: }
                    528:
                    529:
                    530: /*
                    531:  * My PM interrupt routine for PB1XX series
                    532:  */
                    533: int
                    534: pm_intr_pm1(void *arg)
                    535: {
                    536:        int s;
                    537:        int rval;
                    538:        PMData pmdata;
                    539:
                    540:        s = splhigh();
                    541:
                    542:        PM_VIA_CLR_INTR();                              /* clear VIA1 interrupt */
                    543:
                    544:        /* ask PM what happend */
                    545:        pmdata.command = 0x78;
                    546:        pmdata.num_data = 0;
                    547:        pmdata.data[0] = pmdata.data[1] = 0;
                    548:        pmdata.s_buf = &pmdata.data[2];
                    549:        pmdata.r_buf = &pmdata.data[2];
                    550:        rval = pm_pmgrop_pm1(&pmdata);
                    551:        if (rval != 0) {
                    552: #ifdef ADB_DEBUG
                    553:                if (adb_debug)
                    554:                        printf("pm: PM is not ready. error code=%08x\n", rval);
                    555: #endif
                    556:                splx(s);
                    557:        }
                    558:
                    559:        if ((pmdata.data[2] & 0x10) == 0x10) {
                    560:                if ((pmdata.data[2] & 0x0f) == 0) {
                    561:                        /* ADB data that were requested by TALK command */
                    562:                        pm_adb_get_TALK_result(&pmdata);
                    563:                } else if ((pmdata.data[2] & 0x08) == 0x8) {
                    564:                        /* PM is requesting to poll  */
                    565:                        pm_adb_poll_next_device_pm1(&pmdata);
                    566:                } else if ((pmdata.data[2] & 0x04) == 0x4) {
                    567:                        /* ADB device event */
                    568:                        pm_adb_get_ADB_data(&pmdata);
                    569:                }
                    570:        } else {
                    571: #ifdef ADB_DEBUG
                    572:                if (adb_debug)
                    573:                        pm_printerr("driver does not supported this event.",
                    574:                            rval, pmdata.num_data, pmdata.data);
                    575: #endif
                    576:        }
                    577:
                    578:        splx(s);
                    579:
                    580:        return (1);
                    581: }
                    582:
                    583:
                    584:
                    585: /*
                    586:  * Functions for the PB Duo series and the PB 5XX series
                    587:  */
                    588:
                    589: /*
                    590:  * Receive data from PM for the PB Duo series and the PB 5XX series
                    591:  */
                    592: int
                    593: pm_receive_pm2(u_char *data)
                    594: {
                    595:        int i;
                    596:        int rval;
                    597:
                    598:        rval = 0xffffcd34;
                    599:
                    600:        switch (1) {
                    601:        default:
                    602:                /* set VIA SR to input mode */
                    603:                via_reg(VIA1, vACR) |= 0x0c;
                    604:                via_reg(VIA1, vACR) &= ~0x10;
                    605:                i = PM_SR();
                    606:
                    607:                PM_SET_STATE_ACKOFF();
                    608:                if (pm_wait_busy((int)ADBDelay*32) != 0)
                    609:                        break;          /* timeout */
                    610:
                    611:                PM_SET_STATE_ACKON();
                    612:                rval = 0xffffcd33;
                    613:                if (pm_wait_free((int)ADBDelay*32) == 0)
                    614:                        break;          /* timeout */
                    615:
                    616:                *data = PM_SR();
                    617:                rval = 0;
                    618:
                    619:                break;
                    620:        }
                    621:
                    622:        PM_SET_STATE_ACKON();
                    623:        via_reg(VIA1, vACR) |= 0x1c;
                    624:
                    625:        return rval;
                    626: }
                    627:
                    628:
                    629:
                    630: /*
                    631:  * Send data to PM for the PB Duo series and the PB 5XX series
                    632:  */
                    633: int
                    634: pm_send_pm2(u_char data)
                    635: {
                    636:        int rval;
                    637:
                    638:        via_reg(VIA1, vACR) |= 0x1c;
                    639:        PM_SR() = data;
                    640:
                    641:        PM_SET_STATE_ACKOFF();
                    642:        if (pm_wait_busy((int)ADBDelay*32) == 0) {
                    643:                PM_SET_STATE_ACKON();
                    644:                if (pm_wait_free((int)ADBDelay*32) != 0)
                    645:                        rval = 0;
                    646:                else
                    647:                        rval = 0xffffcd35;
                    648:        } else {
                    649:                rval = 0xffffcd36;
                    650:        }
                    651:
                    652:        PM_SET_STATE_ACKON();
                    653:        via_reg(VIA1, vACR) |= 0x1c;
                    654:
                    655:        return rval;
                    656: }
                    657:
                    658:
                    659:
                    660: /*
                    661:  * My PMgrOp routine for the PB Duo series and the PB 5XX series
                    662:  */
                    663: int
                    664: pm_pmgrop_pm2(PMData *pmdata)
                    665: {
                    666:        int i;
                    667:        int s;
                    668:        u_char via1_vIER;
                    669:        int rval = 0;
                    670:        int num_pm_data = 0;
                    671:        u_char pm_cmd;
                    672:        short pm_num_rx_data;
                    673:        u_char pm_data;
                    674:        u_char *pm_buf;
                    675:
                    676:        s = splhigh();
                    677:
                    678:        /* disable all inetrrupts but PM */
                    679:        via1_vIER = 0x10;
                    680:        via1_vIER &= via_reg(VIA1, vIER);
                    681:        via_reg(VIA1, vIER) = via1_vIER;
                    682:        if (via1_vIER != 0x0)
                    683:                via1_vIER |= 0x80;
                    684:
                    685:        switch (pmdata->command) {
                    686:        default:
                    687:                /* wait until PM is free */
                    688:                pm_cmd = (u_char)(pmdata->command & 0xff);
                    689:                rval = 0xcd38;
                    690:                if (pm_wait_free(ADBDelay * 4) == 0)
                    691:                        break;                  /* timeout */
                    692:
                    693:                if (HwCfgFlags3 & 0x00200000) {
                    694:                        /* PB 160, PB 165(c), PB 180(c)? */
                    695:                        int xdelay = ADBDelay * 16;
                    696:
                    697:                        via_reg(VIA2, vDirA) = 0x00;
                    698:                        while ((via_reg(VIA2, 0x200) == 0x07) &&
                    699:                            (xdelay >= 0))
                    700:                                xdelay--;
                    701:
                    702:                        if (xdelay < 0) {
                    703:                                rval = 0xffffcd38;
                    704:                                break;          /* timeout */
                    705:                        }
                    706:                }
                    707:
                    708:                /* send PM command */
                    709:                if ((rval = pm_send_pm2((u_char)(pm_cmd & 0xff))))
                    710:                        break;                          /* timeout */
                    711:
                    712:                /* send number of PM data */
                    713:                num_pm_data = pmdata->num_data;
                    714:                if (HwCfgFlags3 & 0x00020000) {         /* PB Duo, PB 5XX */
                    715:                        if (pm_send_cmd_type[pm_cmd] < 0) {
                    716:                                if ((rval = pm_send_pm2((u_char)(num_pm_data & 0xff))) != 0)
                    717:                                        break;          /* timeout */
                    718:                                pmdata->command = 0;
                    719:                        }
                    720:                } else {                                /* PB 1XX series ? */
                    721:                        if ((rval = pm_send_pm2((u_char)(num_pm_data & 0xff))) != 0)
                    722:                                break;                  /* timeout */
                    723:                }
                    724:                /* send PM data */
                    725:                pm_buf = (u_char *)pmdata->s_buf;
                    726:                for (i = 0 ; i < num_pm_data; i++)
                    727:                        if ((rval = pm_send_pm2(pm_buf[i])) != 0)
                    728:                                break;                  /* timeout */
                    729:                if (i != num_pm_data)
                    730:                        break;                          /* timeout */
                    731:
                    732:
                    733:                /* check if PM will send me data  */
                    734:                pm_num_rx_data = pm_receive_cmd_type[pm_cmd];
                    735:                pmdata->num_data = pm_num_rx_data;
                    736:                if (pm_num_rx_data == 0) {
                    737:                        rval = 0;
                    738:                        break;                          /* no return data */
                    739:                }
                    740:
                    741:                /* receive PM command */
                    742:                pm_data = pmdata->command;
                    743:                if (HwCfgFlags3 & 0x00020000) {         /* PB Duo, PB 5XX */
                    744:                        pm_num_rx_data--;
                    745:                        if (pm_num_rx_data == 0)
                    746:                                if ((rval = pm_receive_pm2(&pm_data)) != 0) {
                    747:                                        rval = 0xffffcd37;
                    748:                                        break;
                    749:                                }
                    750:                        pmdata->command = pm_data;
                    751:                } else {                                /* PB 1XX series ? */
                    752:                        if ((rval = pm_receive_pm2(&pm_data)) != 0) {
                    753:                                rval = 0xffffcd37;
                    754:                                break;
                    755:                        }
                    756:                        pmdata->command = pm_data;
                    757:                }
                    758:
                    759:                /* receive number of PM data */
                    760:                if (HwCfgFlags3 & 0x00020000) {         /* PB Duo, PB 5XX */
                    761:                        if (pm_num_rx_data < 0) {
                    762:                                if ((rval = pm_receive_pm2(&pm_data)) != 0)
                    763:                                        break;          /* timeout */
                    764:                                num_pm_data = pm_data;
                    765:                        } else
                    766:                                num_pm_data = pm_num_rx_data;
                    767:                        pmdata->num_data = num_pm_data;
                    768:                } else {                                /* PB 1XX serias ? */
                    769:                        if ((rval = pm_receive_pm2(&pm_data)) != 0)
                    770:                                break;                  /* timeout */
                    771:                        num_pm_data = pm_data;
                    772:                        pmdata->num_data = num_pm_data;
                    773:                }
                    774:
                    775:                /* receive PM data */
                    776:                pm_buf = (u_char *)pmdata->r_buf;
                    777:                for (i = 0; i < num_pm_data; i++) {
                    778:                        if ((rval = pm_receive_pm2(&pm_data)) != 0)
                    779:                                break;                  /* timeout */
                    780:                        pm_buf[i] = pm_data;
                    781:                }
                    782:
                    783:                rval = 0;
                    784:        }
                    785:
                    786:        /* restore former value */
                    787:        via_reg(VIA1, vIER) = via1_vIER;
                    788:        splx(s);
                    789:
                    790:        return rval;
                    791: }
                    792:
                    793:
                    794: /*
                    795:  * My PM interrupt routine for the PB Duo series and the PB 5XX series
                    796:  */
                    797: int
                    798: pm_intr_pm2(void *arg)
                    799: {
                    800:        int s;
                    801:        int rval;
                    802:        PMData pmdata;
                    803:
                    804:        s = splhigh();
                    805:
                    806:        PM_VIA_CLR_INTR();                      /* clear VIA1 interrupt */
                    807:                                                /* ask PM what happend */
                    808:        pmdata.command = 0x78;
                    809:        pmdata.num_data = 0;
                    810:        pmdata.s_buf = &pmdata.data[2];
                    811:        pmdata.r_buf = &pmdata.data[2];
                    812:        rval = pm_pmgrop_pm2(&pmdata);
                    813:        if (rval != 0) {
                    814: #ifdef ADB_DEBUG
                    815:                if (adb_debug)
                    816:                        printf("pm: PM is not ready. error code: %08x\n", rval);
                    817: #endif
                    818:                splx(s);
                    819:        }
                    820:
                    821:        switch ((u_int)(pmdata.data[2] & 0xff)) {
                    822:        case 0x00:                      /* 1 sec interrupt? */
                    823:                break;
                    824:        case 0x80:                      /* 1 sec interrupt? */
                    825:                pm_counter++;
                    826:                break;
                    827:        case 0x08:                      /* Brightness/Contrast button on LCD panel */
                    828:                /* get brightness and contrast of the LCD */
                    829:                pm_LCD_brightness = (u_int)pmdata.data[3] & 0xff;
                    830:                pm_LCD_contrast = (u_int)pmdata.data[4] & 0xff;
                    831: /*
                    832:                pm_printerr("#08", rval, pmdata.num_data, pmdata.data);
                    833:                pmdata.command = 0x33;
                    834:                pmdata.num_data = 1;
                    835:                pmdata.s_buf = pmdata.data;
                    836:                pmdata.r_buf = pmdata.data;
                    837:                pmdata.data[0] = pm_LCD_contrast;
                    838:                rval = pm_pmgrop_pm2(&pmdata);
                    839:                pm_printerr("#33", rval, pmdata.num_data, pmdata.data);
                    840: */
                    841:                /* this is an experimental code */
                    842:                pmdata.command = 0x41;
                    843:                pmdata.num_data = 1;
                    844:                pmdata.s_buf = pmdata.data;
                    845:                pmdata.r_buf = pmdata.data;
                    846:                pm_LCD_brightness = 0x7f - pm_LCD_brightness / 2;
                    847:                if (pm_LCD_brightness < 0x25)
                    848:                        pm_LCD_brightness = 0x25;
                    849:                if (pm_LCD_brightness > 0x5a)
                    850:                        pm_LCD_brightness = 0x7f;
                    851:                pmdata.data[0] = pm_LCD_brightness;
                    852:                rval = pm_pmgrop_pm2(&pmdata);
                    853:                break;
                    854:        case 0x10:                      /* ADB data that were requested by TALK command */
                    855:        case 0x14:
                    856:                pm_adb_get_TALK_result(&pmdata);
                    857:                break;
                    858:        case 0x16:                      /* ADB device event */
                    859:        case 0x18:
                    860:        case 0x1e:
                    861:                pm_adb_get_ADB_data(&pmdata);
                    862:                break;
                    863:        default:
                    864: #ifdef ADB_DEBUG
                    865:                if (adb_debug)
                    866:                        pm_printerr("driver does not supported this event.",
                    867:                            pmdata.data[2], pmdata.num_data,
                    868:                            pmdata.data);
                    869: #endif
                    870:                break;
                    871:        }
                    872:
                    873:        splx(s);
                    874:
                    875:        return (1);
                    876: }
                    877:
                    878:
                    879: /*
                    880:  * My PMgrOp routine
                    881:  */
                    882: int
                    883: pmgrop(PMData *pmdata)
                    884: {
                    885:        switch (pmHardware) {
                    886:        case PM_HW_PB1XX:
                    887:                return (pm_pmgrop_pm1(pmdata));
                    888:                break;
                    889:        case PM_HW_PB5XX:
                    890:                return (pm_pmgrop_pm2(pmdata));
                    891:                break;
                    892:        default:
                    893:                return 1;
                    894:        }
                    895: }
                    896:
                    897: int
                    898: pm_intr(void *arg)
                    899: {
                    900:        switch (pmHardware) {
                    901:        case PM_HW_PB1XX:
                    902:                return (pm_intr_pm1(arg));
                    903:        case PM_HW_PB5XX:
                    904:                return (pm_intr_pm2(arg));
                    905:        default:
                    906:                return (-1);
                    907:        }
                    908: }
                    909:
                    910: void
                    911: pm_hw_setup(struct device *self)
                    912: {
                    913:        switch (pmHardware) {
                    914:        case PM_HW_PB1XX:
                    915:                via1_register_irq(4, pm_intr_pm1, self, self->dv_xname);
                    916:                PM_VIA_CLR_INTR();
                    917:                break;
                    918:        case PM_HW_PB5XX:
                    919:                via1_register_irq(4, pm_intr_pm2, self, self->dv_xname);
                    920:                PM_VIA_CLR_INTR();
                    921:                break;
                    922:        default:
                    923:                break;
                    924:        }
                    925: }
                    926:
                    927:
                    928: /*
                    929:  * Synchronous ADBOp routine for the Power Manager
                    930:  */
                    931: int
                    932: pm_adb_op(u_char *buffer, void *compRout, void *data, int command)
                    933: {
                    934:        int i;
                    935:        int s;
                    936:        int rval;
                    937:        int xdelay;
                    938:        PMData pmdata;
                    939:        struct adbCommand packet;
                    940:
                    941:        if (adbWaiting == 1)
                    942:                return 1;
                    943:
                    944:        s = splhigh();
                    945:        via_reg(VIA1, vIER) = 0x10;
                    946:
                    947:        adbBuffer = buffer;
                    948:        adbCompRout = compRout;
                    949:        adbCompData = data;
                    950:
                    951:        pmdata.command = 0x20;
                    952:        pmdata.s_buf = pmdata.data;
                    953:        pmdata.r_buf = pmdata.data;
                    954:
                    955:        if ((command & 0xc) == 0x8) {           /* if the command is LISTEN, add number of ADB data to number of PM data */
                    956:                if (buffer != (u_char *)0)
                    957:                        pmdata.num_data = buffer[0] + 3;
                    958:        } else {
                    959:                pmdata.num_data = 3;
                    960:        }
                    961:
                    962:        pmdata.data[0] = (u_char)(command & 0xff);
                    963:        pmdata.data[1] = 0;
                    964:        if ((command & 0xc) == 0x8) {           /* if the command is LISTEN, copy ADB data to PM buffer */
                    965:                if ((buffer != (u_char *)0) && (buffer[0] <= 24)) {
                    966:                        pmdata.data[2] = buffer[0];             /* number of data */
                    967:                        for (i = 0; i < buffer[0]; i++)
                    968:                                pmdata.data[3 + i] = buffer[1 + i];
                    969:                } else
                    970:                        pmdata.data[2] = 0;
                    971:        } else
                    972:                pmdata.data[2] = 0;
                    973:
                    974:        if ((command & 0xc) != 0xc) {           /* if the command is not TALK */
                    975:                /* set up stuff fNULLor adb_pass_up */
                    976:                packet.data[0] = 1 + pmdata.data[2];
                    977:                packet.data[1] = command;
                    978:                for (i = 0; i < pmdata.data[2]; i++)
                    979:                        packet.data[i+2] = pmdata.data[i+3];
                    980:                packet.saveBuf = adbBuffer;
                    981:                packet.compRout = adbCompRout;
                    982:                packet.compData = adbCompData;
                    983:                packet.cmd = command;
                    984:                packet.unsol = 0;
                    985:                packet.ack_only = 1;
                    986:                adb_polling = 1;
                    987:                adb_pass_up(&packet);
                    988:                adb_polling = 0;
                    989:        }
                    990:
                    991:        rval = pmgrop(&pmdata);
                    992:        if (rval != 0) {
                    993:                splx(s);
                    994:                return 1;
                    995:        }
                    996:
                    997:        adbWaiting = 1;
                    998:        adbWaitingCmd = command;
                    999:
                   1000:        PM_VIA_INTR_ENABLE();
                   1001:
                   1002:        /* wait until the PM interrupt has occurred */
                   1003:        xdelay = 0x80000;
                   1004:        while (adbWaiting == 1) {
                   1005:                switch (mac68k_machine.machineid) {
                   1006:                case MACH_MACPB150:
                   1007:                case MACH_MACPB210:
                   1008:                case MACH_MACPB230:     /* daishi tested with Duo230 */
                   1009:                case MACH_MACPB250:
                   1010:                case MACH_MACPB270:
                   1011:                case MACH_MACPB280:
                   1012:                case MACH_MACPB280C:
                   1013:                case MACH_MACPB190:
                   1014:                case MACH_MACPB190CS:
                   1015:                        pm_intr((void *)0);
                   1016:                        break;
                   1017:                default:
                   1018:                        if ((via_reg(VIA1, vIFR) & 0x10) == 0x10)
                   1019:                                pm_intr((void *)0);
                   1020:                        break;
                   1021:                }
                   1022: #ifdef PM_GRAB_SI
                   1023:                (void)intr_dispatch(0x70);      /* grab any serial interrupts */
                   1024: #endif
                   1025:                if ((--xdelay) < 0) {
                   1026:                        splx(s);
                   1027:                        return 1;
                   1028:                }
                   1029:        }
                   1030:
                   1031:        /* this command enables the interrupt by operating ADB devices */
                   1032:        if (HwCfgFlags3 & 0x00020000) {         /* PB Duo series, PB 5XX series */
                   1033:                pmdata.command = 0x20;
                   1034:                pmdata.num_data = 4;
                   1035:                pmdata.s_buf = pmdata.data;
                   1036:                pmdata.r_buf = pmdata.data;
                   1037:                pmdata.data[0] = 0x00;
                   1038:                pmdata.data[1] = 0x86;  /* magic spell for awaking the PM */
                   1039:                pmdata.data[2] = 0x00;
                   1040:                pmdata.data[3] = 0x0c;  /* each bit may express the existent ADB device */
                   1041:        } else {                                /* PB 1XX series */
                   1042:                pmdata.command = 0x20;
                   1043:                pmdata.num_data = 3;
                   1044:                pmdata.s_buf = pmdata.data;
                   1045:                pmdata.r_buf = pmdata.data;
                   1046:                pmdata.data[0] = (u_char)(command & 0xf0) | 0xc;
                   1047:                pmdata.data[1] = 0x04;
                   1048:                pmdata.data[2] = 0x00;
                   1049:        }
                   1050:        rval = pmgrop(&pmdata);
                   1051:
                   1052:        splx(s);
                   1053:        return rval;
                   1054: }
                   1055:
                   1056:
                   1057: void
                   1058: pm_adb_get_TALK_result(PMData *pmdata)
                   1059: {
                   1060:        int i;
                   1061:        struct adbCommand packet;
                   1062:
                   1063:        /* set up data for adb_pass_up */
                   1064:        packet.data[0] = pmdata->num_data-1;
                   1065:        packet.data[1] = pmdata->data[3];
                   1066:        for (i = 0; i <packet.data[0]-1; i++)
                   1067:                packet.data[i+2] = pmdata->data[i+4];
                   1068:
                   1069:        packet.saveBuf = adbBuffer;
                   1070:        packet.compRout = adbCompRout;
                   1071:        packet.compData = adbCompData;
                   1072:        packet.unsol = 0;
                   1073:        packet.ack_only = 0;
                   1074:        adb_polling = 1;
                   1075:        adb_pass_up(&packet);
                   1076:        adb_polling = 0;
                   1077:
                   1078:        adbWaiting = 0;
                   1079:        adbBuffer = (long)0;
                   1080:        adbCompRout = (long)0;
                   1081:        adbCompData = (long)0;
                   1082: }
                   1083:
                   1084:
                   1085: void
                   1086: pm_adb_get_ADB_data(PMData *pmdata)
                   1087: {
                   1088:        int i;
                   1089:        struct adbCommand packet;
                   1090:
                   1091:        /* set up data for adb_pass_up */
                   1092:        packet.data[0] = pmdata->num_data-1;    /* number of raw data */
                   1093:        packet.data[1] = pmdata->data[3];       /* ADB command */
                   1094:        for (i = 0; i <packet.data[0]-1; i++)
                   1095:                packet.data[i+2] = pmdata->data[i+4];
                   1096:        packet.unsol = 1;
                   1097:        packet.ack_only = 0;
                   1098:        adb_pass_up(&packet);
                   1099: }
                   1100:
                   1101:
                   1102: void
                   1103: pm_adb_poll_next_device_pm1(PMData *pmdata)
                   1104: {
                   1105:        int i;
                   1106:        int ndid;
                   1107:        u_short bendid = 0x1;
                   1108:        int rval;
                   1109:        PMData tmp_pmdata;
                   1110:
                   1111:        /* find another existent ADB device to poll */
                   1112:        for (i = 1; i < 16; i++) {
                   1113:                ndid = (ADB_CMDADDR(pmdata->data[3]) + i) & 0xf;
                   1114:                bendid <<= ndid;
                   1115:                if ((pm_existent_ADB_devices & bendid) != 0)
                   1116:                        break;
                   1117:        }
                   1118:
                   1119:        /* poll the other device */
                   1120:        tmp_pmdata.command = 0x20;
                   1121:        tmp_pmdata.num_data = 3;
                   1122:        tmp_pmdata.s_buf = tmp_pmdata.data;
                   1123:        tmp_pmdata.r_buf = tmp_pmdata.data;
                   1124:        tmp_pmdata.data[0] = (u_char)(ndid << 4) | 0xc;
                   1125:        tmp_pmdata.data[1] = 0x04;      /* magic spell for awaking the PM */
                   1126:        tmp_pmdata.data[2] = 0x00;
                   1127:        rval = pmgrop(&tmp_pmdata);
                   1128: }

CVSweb