1 /* $NetBSD: pm_direct.c,v 1.27 2005/12/24 20:07:15 perry Exp $ */
4 * Copyright (C) 1997 Takashi Hamada
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Takashi Hamada
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 /* From: pm_direct.c 1.3 03/18/98 Takashi Hamada */
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: pm_direct.c,v 1.27 2005/12/24 20:07:15 perry Exp $");
45 /* #define PM_GRAB_SI 1 */
47 #include <sys/types.h>
48 #include <sys/systm.h>
50 #include <machine/viareg.h>
51 #include <machine/param.h>
52 #include <machine/cpu.h>
53 #include <machine/adbsys.h>
55 #include <mac68k/mac68k/macrom.h>
56 #include <mac68k/dev/adbvar.h>
57 #include <mac68k/dev/pm_direct.h>
59 /* hardware dependent values */
60 extern u_short ADBDelay
;
61 extern u_int32_t HwCfgFlags3
;
62 extern struct mac68k_machine_S mac68k_machine
;
65 /* define the types of the Power Manager */
66 #define PM_HW_UNKNOWN 0x00 /* don't know */
67 #define PM_HW_PB1XX 0x01 /* PowerBook 1XX series */
68 #define PM_HW_PB5XX 0x02 /* PowerBook Duo and 5XX series */
71 #define PM_SR() via_reg(VIA1, vSR)
72 #define PM_VIA_INTR_ENABLE() via_reg(VIA1, vIER) = 0x90
73 #define PM_VIA_INTR_DISABLE() via_reg(VIA1, vIER) = 0x10
74 #define PM_VIA_CLR_INTR() via_reg(VIA1, vIFR) = 0x90
75 #define PM_SET_STATE_ACKON() via_reg(VIA2, vBufB) |= 0x04
76 #define PM_SET_STATE_ACKOFF() via_reg(VIA2, vBufB) &= ~0x04
77 #define PM_IS_ON (0x02 == (via_reg(VIA2, vBufB) & 0x02))
78 #define PM_IS_OFF (0x00 == (via_reg(VIA2, vBufB) & 0x02))
81 * Variables for internal use
83 int pmHardware
= PM_HW_UNKNOWN
;
84 u_short pm_existent_ADB_devices
= 0x0; /* each bit expresses the existent ADB device */
85 u_int pm_LCD_brightness
= 0x0;
86 u_int pm_LCD_contrast
= 0x0;
87 u_int pm_counter
= 0; /* clock count */
89 /* these values shows that number of data returned after 'send' cmd is sent */
90 char pm_send_cmd_type
[] = {
91 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
95 0xff, 0x00, 0x02, 0x01, 0x01, 0xff, 0xff, 0xff,
96 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
97 0x04, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
98 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff,
99 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
100 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 0x01, 0x00, 0x02, 0x02, 0xff, 0x01, 0x03, 0x01,
102 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
103 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
105 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
106 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x04, 0x04,
107 0x04, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
108 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109 0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
110 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
111 0x02, 0x02, 0x02, 0x04, 0xff, 0x00, 0xff, 0xff,
112 0x01, 0x01, 0x03, 0x02, 0xff, 0xff, 0xff, 0xff,
113 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
114 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
115 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
116 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
117 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
118 0x01, 0x01, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
119 0xff, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
120 0x03, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
125 /* these values shows that number of data returned after 'receive' cmd is sent */
126 char pm_receive_cmd_type
[] = {
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x05, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x02, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x04, 0x04, 0x03, 0x09, 0xff, 0xff, 0xff, 0xff,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x02, 0x02, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff,
155 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
163 * Define the private functions
168 void pm_printerr(const char *, int, int, char *);
171 int pm_wait_busy(int);
172 int pm_wait_free(int);
174 /* these functions are for the PB1XX series */
175 int pm_receive_pm1(u_char
*);
176 int pm_send_pm1(u_char
, int);
177 int pm_pmgrop_pm1(PMData
*);
178 void pm_intr_pm1(void *);
180 /* these functions are for the PB Duo series and the PB 5XX series */
181 int pm_receive_pm2(u_char
*);
182 int pm_send_pm2(u_char
);
183 int pm_pmgrop_pm2(PMData
*);
184 void pm_intr_pm2(void *);
186 /* this function is MRG-Based (for testing) */
187 int pm_pmgrop_mrg(PMData
*);
189 /* these functions are called from adb_direct.c */
190 void pm_setup_adb(void);
191 void pm_check_adb_devices(int);
192 void pm_intr(void *);
193 int pm_adb_op(u_char
*, void *, void *, int);
194 void pm_hw_setup(void);
196 /* these functions also use the variables of adb_direct.c */
197 void pm_adb_get_TALK_result(PMData
*);
198 void pm_adb_get_ADB_data(PMData
*);
199 void pm_adb_poll_next_device_pm1(PMData
*);
203 * These variables are in adb_direct.c.
205 extern u_char
*adbBuffer
; /* pointer to user data area */
206 extern void *adbCompRout
; /* pointer to the completion routine */
207 extern void *adbCompData
; /* pointer to the completion routine data */
208 extern int adbWaiting
; /* waiting for return data from the device */
209 extern int adbWaitingCmd
; /* ADB command we are waiting for */
210 extern int adbStarting
; /* doing ADB reinit, so do "polling" differently */
212 #define ADB_MAX_MSG_LENGTH 16
213 #define ADB_MAX_HDR_LENGTH 8
215 u_char header
[ADB_MAX_HDR_LENGTH
]; /* not used yet */
216 u_char data
[ADB_MAX_MSG_LENGTH
]; /* packet data only */
217 u_char
*saveBuf
; /* where to save result */
218 u_char
*compRout
; /* completion routine pointer */
219 u_char
*compData
; /* completion routine data pointer */
220 u_int cmd
; /* the original command for this data */
221 u_int unsol
; /* 1 if packet was unsolicited */
222 u_int ack_only
; /* 1 for no special processing */
224 extern void adb_pass_up(struct adbCommand
*);
228 * This function dumps contents of the PMData
231 pm_printerr(const char *ttl
, int rval
, int num
, char *data
)
235 printf("pm: %s:%04x %02x ", ttl
, rval
, num
);
236 for (i
= 0; i
< num
; i
++)
237 printf("%02x ", data
[i
]);
245 * Check the hardware type of the Power Manager
250 switch (mac68k_machine
.machineid
) {
259 pmHardware
= PM_HW_PB1XX
;
270 case MACH_MACPB190CS
:
271 pmHardware
= PM_HW_PB5XX
;
280 * Check the existent ADB devices
283 pm_check_adb_devices(int id
)
288 pm_existent_ADB_devices
|= ed
;
293 * Wait until PM IC is busy
296 pm_wait_busy(int xdelay
)
300 (void)intr_dispatch(0x70); /* grab any serial interrupts */
303 return 1; /* timeout */
310 * Wait until PM IC is free
313 pm_wait_free(int xdelay
)
317 (void)intr_dispatch(0x70); /* grab any serial interrupts */
320 return 0; /* timeout */
328 * Functions for the PB1XX series
332 * Receive data from PM for the PB1XX series
335 pm_receive_pm1(u_char
*data
)
337 int rval
= 0xffffcd34;
339 via_reg(VIA2
, vDirA
) = 0x00;
343 if (pm_wait_busy(0x40) != 0)
346 PM_SET_STATE_ACKOFF();
347 *data
= via_reg(VIA2
, 0x200);
350 if (pm_wait_free(0x40) == 0)
357 PM_SET_STATE_ACKON();
358 via_reg(VIA2
, vDirA
) = 0x00;
366 * Send data to PM for the PB1XX series
369 pm_send_pm1(u_char data
, int timo
)
373 via_reg(VIA2
, vDirA
) = 0xff;
374 via_reg(VIA2
, 0x200) = data
;
376 PM_SET_STATE_ACKOFF();
378 if (pm_wait_busy(0x400) == 0) {
380 if (pm_wait_busy(timo
) == 0) {
382 PM_SET_STATE_ACKON();
383 if (pm_wait_free(0x40) != 0)
391 PM_SET_STATE_ACKON();
392 via_reg(VIA2
, vDirA
) = 0x00;
399 * My PMgrOp routine for the PB1XX series
402 pm_pmgrop_pm1(PMData
*pmdata
)
406 u_char via1_vIER
, via1_vDirA
;
413 /* disable all inetrrupts but PM */
414 via1_vIER
= via_reg(VIA1
, vIER
);
415 PM_VIA_INTR_DISABLE();
417 via1_vDirA
= via_reg(VIA1
, vDirA
);
419 switch (pmdata
->command
) {
421 for (i
= 0; i
< 7; i
++) {
422 via_reg(VIA2
, vDirA
) = 0x00;
424 /* wait until PM is free */
425 if (pm_wait_free(ADBDelay
) == 0) { /* timeout */
426 via_reg(VIA2
, vDirA
) = 0x00;
427 /* restore formar value */
428 via_reg(VIA1
, vDirA
) = via1_vDirA
;
429 via_reg(VIA1
, vIER
) = via1_vIER
;
433 switch (mac68k_machine
.machineid
) {
441 int xdelay
= ADBDelay
* 16;
443 via_reg(VIA2
, vDirA
) = 0x00;
444 while ((via_reg(VIA2
, 0x200) == 0x7f) && (xdelay
>= 0))
447 if (xdelay
< 0) { /* timeout */
448 via_reg(VIA2
, vDirA
) = 0x00;
449 /* restore formar value */
450 via_reg(VIA1
, vIER
) = via1_vIER
;
458 via1_vDirA
= via_reg(VIA1
, vDirA
);
459 via_reg(VIA1
, vDirA
) &= 0x7f;
461 pm_cmd
= (u_char
)(pmdata
->command
& 0xff);
462 if ((rval
= pm_send_pm1(pm_cmd
, ADBDelay
* 8)) == 0)
463 break; /* send command succeeded */
465 via_reg(VIA1
, vDirA
) = via1_vDirA
;
469 /* failed to send a command */
471 via_reg(VIA2
, vDirA
) = 0x00;
472 /* restore formar value */
473 via_reg(VIA1
, vDirA
) = via1_vDirA
;
474 via_reg(VIA1
, vIER
) = via1_vIER
;
480 /* send # of PM data */
481 num_pm_data
= pmdata
->num_data
;
482 if ((rval
= pm_send_pm1((u_char
)(num_pm_data
& 0xff), ADBDelay
* 8)) != 0)
486 pm_buf
= (u_char
*)pmdata
->s_buf
;
487 for (i
= 0; i
< num_pm_data
; i
++)
488 if ((rval
= pm_send_pm1(pm_buf
[i
], ADBDelay
* 8)) != 0)
490 if ((i
!= num_pm_data
) && (num_pm_data
!= 0))
493 /* Will PM IC return data? */
494 if ((pm_cmd
& 0x08) == 0) {
496 break; /* no returned data */
500 if (pm_wait_busy(ADBDelay
) != 0)
503 /* receive PM command */
504 if ((rval
= pm_receive_pm1(&pm_data
)) != 0)
507 pmdata
->command
= pm_data
;
509 /* receive number of PM data */
510 if ((rval
= pm_receive_pm1(&pm_data
)) != 0)
512 num_pm_data
= pm_data
;
513 pmdata
->num_data
= num_pm_data
;
515 /* receive PM data */
516 pm_buf
= (u_char
*)pmdata
->r_buf
;
517 for (i
= 0; i
< num_pm_data
; i
++) {
518 if ((rval
= pm_receive_pm1(&pm_data
)) != 0)
526 via_reg(VIA2
, vDirA
) = 0x00;
528 /* restore formar value */
529 via_reg(VIA1
, vDirA
) = via1_vDirA
;
530 via_reg(VIA1
, vIER
) = via1_vIER
;
539 * My PM interrupt routine for PB1XX series
542 pm_intr_pm1(void *arg
)
550 PM_VIA_CLR_INTR(); /* clear VIA1 interrupt */
552 /* ask PM what happend */
553 pmdata
.command
= 0x78;
555 pmdata
.data
[0] = pmdata
.data
[1] = 0;
556 pmdata
.s_buf
= &pmdata
.data
[2];
557 pmdata
.r_buf
= &pmdata
.data
[2];
558 rval
= pm_pmgrop_pm1(&pmdata
);
562 printf("pm: PM is not ready. error code=%08x\n", rval
);
567 if ((pmdata
.data
[2] & 0x10) == 0x10) {
568 if ((pmdata
.data
[2] & 0x0f) == 0) {
569 /* ADB data that were requested by TALK command */
570 pm_adb_get_TALK_result(&pmdata
);
571 } else if ((pmdata
.data
[2] & 0x08) == 0x8) {
572 /* PM is requesting to poll */
573 pm_adb_poll_next_device_pm1(&pmdata
);
574 } else if ((pmdata
.data
[2] & 0x04) == 0x4) {
575 /* ADB device event */
576 pm_adb_get_ADB_data(&pmdata
);
581 pm_printerr("driver does not supported this event.",
582 rval
, pmdata
.num_data
, pmdata
.data
);
592 * Functions for the PB Duo series and the PB 5XX series
596 * Receive data from PM for the PB Duo series and the PB 5XX series
599 pm_receive_pm2(u_char
*data
)
608 /* set VIA SR to input mode */
609 via_reg(VIA1
, vACR
) |= 0x0c;
610 via_reg(VIA1
, vACR
) &= ~0x10;
613 PM_SET_STATE_ACKOFF();
614 if (pm_wait_busy((int)ADBDelay
*32) != 0)
617 PM_SET_STATE_ACKON();
619 if (pm_wait_free((int)ADBDelay
*32) == 0)
628 PM_SET_STATE_ACKON();
629 via_reg(VIA1
, vACR
) |= 0x1c;
637 * Send data to PM for the PB Duo series and the PB 5XX series
640 pm_send_pm2(u_char data
)
644 via_reg(VIA1
, vACR
) |= 0x1c;
647 PM_SET_STATE_ACKOFF();
648 if (pm_wait_busy((int)ADBDelay
*32) == 0) {
649 PM_SET_STATE_ACKON();
650 if (pm_wait_free((int)ADBDelay
*32) != 0)
658 PM_SET_STATE_ACKON();
659 via_reg(VIA1
, vACR
) |= 0x1c;
667 * My PMgrOp routine for the PB Duo series and the PB 5XX series
670 pm_pmgrop_pm2(PMData
*pmdata
)
678 short pm_num_rx_data
;
684 /* disable all inetrrupts but PM */
686 via1_vIER
&= via_reg(VIA1
, vIER
);
687 via_reg(VIA1
, vIER
) = via1_vIER
;
688 if (via1_vIER
!= 0x0)
691 switch (pmdata
->command
) {
693 /* wait until PM is free */
694 pm_cmd
= (u_char
)(pmdata
->command
& 0xff);
696 if (pm_wait_free(ADBDelay
* 4) == 0)
699 if (HwCfgFlags3
& 0x00200000) {
700 /* PB 160, PB 165(c), PB 180(c)? */
701 int xdelay
= ADBDelay
* 16;
703 via_reg(VIA2
, vDirA
) = 0x00;
704 while ((via_reg(VIA2
, 0x200) == 0x07) &&
714 /* send PM command */
715 if ((rval
= pm_send_pm2((u_char
)(pm_cmd
& 0xff))))
718 /* send number of PM data */
719 num_pm_data
= pmdata
->num_data
;
720 if (HwCfgFlags3
& 0x00020000) { /* PB Duo, PB 5XX */
721 if (pm_send_cmd_type
[pm_cmd
] < 0) {
722 if ((rval
= pm_send_pm2((u_char
)(num_pm_data
& 0xff))) != 0)
726 } else { /* PB 1XX series ? */
727 if ((rval
= pm_send_pm2((u_char
)(num_pm_data
& 0xff))) != 0)
731 pm_buf
= (u_char
*)pmdata
->s_buf
;
732 for (i
= 0 ; i
< num_pm_data
; i
++)
733 if ((rval
= pm_send_pm2(pm_buf
[i
])) != 0)
735 if (i
!= num_pm_data
)
739 /* check if PM will send me data */
740 pm_num_rx_data
= pm_receive_cmd_type
[pm_cmd
];
741 pmdata
->num_data
= pm_num_rx_data
;
742 if (pm_num_rx_data
== 0) {
744 break; /* no return data */
747 /* receive PM command */
748 pm_data
= pmdata
->command
;
749 if (HwCfgFlags3
& 0x00020000) { /* PB Duo, PB 5XX */
751 if (pm_num_rx_data
== 0)
752 if ((rval
= pm_receive_pm2(&pm_data
)) != 0) {
756 pmdata
->command
= pm_data
;
757 } else { /* PB 1XX series ? */
758 if ((rval
= pm_receive_pm2(&pm_data
)) != 0) {
762 pmdata
->command
= pm_data
;
765 /* receive number of PM data */
766 if (HwCfgFlags3
& 0x00020000) { /* PB Duo, PB 5XX */
767 if (pm_num_rx_data
< 0) {
768 if ((rval
= pm_receive_pm2(&pm_data
)) != 0)
770 num_pm_data
= pm_data
;
772 num_pm_data
= pm_num_rx_data
;
773 pmdata
->num_data
= num_pm_data
;
774 } else { /* PB 1XX serias ? */
775 if ((rval
= pm_receive_pm2(&pm_data
)) != 0)
777 num_pm_data
= pm_data
;
778 pmdata
->num_data
= num_pm_data
;
781 /* receive PM data */
782 pm_buf
= (u_char
*)pmdata
->r_buf
;
783 for (i
= 0; i
< num_pm_data
; i
++) {
784 if ((rval
= pm_receive_pm2(&pm_data
)) != 0)
792 /* restore former value */
793 via_reg(VIA1
, vIER
) = via1_vIER
;
801 * My PM interrupt routine for the PB Duo series and the PB 5XX series
804 pm_intr_pm2(void *arg
)
812 PM_VIA_CLR_INTR(); /* clear VIA1 interrupt */
813 /* ask PM what happend */
814 pmdata
.command
= 0x78;
816 pmdata
.s_buf
= &pmdata
.data
[2];
817 pmdata
.r_buf
= &pmdata
.data
[2];
818 rval
= pm_pmgrop_pm2(&pmdata
);
822 printf("pm: PM is not ready. error code: %08x\n", rval
);
827 switch ((u_int
)(pmdata
.data
[2] & 0xff)) {
828 case 0x00: /* 1 sec interrupt? */
830 case 0x80: /* 1 sec interrupt? */
833 case 0x08: /* Brightness/Contrast button on LCD panel */
834 /* get brightness and contrast of the LCD */
835 pm_LCD_brightness
= (u_int
)pmdata
.data
[3] & 0xff;
836 pm_LCD_contrast
= (u_int
)pmdata
.data
[4] & 0xff;
838 pm_printerr("#08", rval, pmdata.num_data, pmdata.data);
839 pmdata.command = 0x33;
841 pmdata.s_buf = pmdata.data;
842 pmdata.r_buf = pmdata.data;
843 pmdata.data[0] = pm_LCD_contrast;
844 rval = pm_pmgrop_pm2(&pmdata);
845 pm_printerr("#33", rval, pmdata.num_data, pmdata.data);
847 /* this is an experimental code */
848 pmdata
.command
= 0x41;
850 pmdata
.s_buf
= pmdata
.data
;
851 pmdata
.r_buf
= pmdata
.data
;
852 pm_LCD_brightness
= 0x7f - pm_LCD_brightness
/ 2;
853 if (pm_LCD_brightness
< 0x25)
854 pm_LCD_brightness
= 0x25;
855 if (pm_LCD_brightness
> 0x5a)
856 pm_LCD_brightness
= 0x7f;
857 pmdata
.data
[0] = pm_LCD_brightness
;
858 rval
= pm_pmgrop_pm2(&pmdata
);
860 case 0x10: /* ADB data that were requested by TALK command */
862 pm_adb_get_TALK_result(&pmdata
);
864 case 0x16: /* ADB device event */
867 pm_adb_get_ADB_data(&pmdata
);
872 pm_printerr("driver does not supported this event.",
873 pmdata
.data
[2], pmdata
.num_data
,
884 * MRG-based PMgrOp routine
887 pm_pmgrop_mrg(PMData
*pmdata
)
907 pmgrop(PMData
*pmdata
)
909 switch (pmHardware
) {
911 return (pm_pmgrop_pm1(pmdata
));
914 return (pm_pmgrop_pm2(pmdata
));
917 /* return (pmgrop_mrg(pmdata)); */
924 * My PM interrupt routine
929 switch (pmHardware
) {
945 switch (pmHardware
) {
947 via1_register_irq(4, pm_intr_pm1
, (void *)0);
951 via1_register_irq(4, pm_intr_pm2
, (void *)0);
961 * Synchronous ADBOp routine for the Power Manager
964 pm_adb_op(u_char
*buffer
, void *compRout
, void *data
, int command
)
971 struct adbCommand packet
;
977 via_reg(VIA1
, vIER
) = 0x10;
980 adbCompRout
= compRout
;
983 pmdata
.command
= 0x20;
984 pmdata
.s_buf
= pmdata
.data
;
985 pmdata
.r_buf
= pmdata
.data
;
987 if ((command
& 0xc) == 0x8) { /* if the command is LISTEN, add number of ADB data to number of PM data */
988 if (buffer
!= (u_char
*)0)
989 pmdata
.num_data
= buffer
[0] + 3;
994 pmdata
.data
[0] = (u_char
)(command
& 0xff);
996 if ((command
& 0xc) == 0x8) { /* if the command is LISTEN, copy ADB data to PM buffer */
997 if ((buffer
!= (u_char
*)0) && (buffer
[0] <= 24)) {
998 pmdata
.data
[2] = buffer
[0]; /* number of data */
999 for (i
= 0; i
< buffer
[0]; i
++)
1000 pmdata
.data
[3 + i
] = buffer
[1 + i
];
1006 if ((command
& 0xc) != 0xc) { /* if the command is not TALK */
1007 /* set up stuff fNULLor adb_pass_up */
1008 packet
.data
[0] = 1 + pmdata
.data
[2];
1009 packet
.data
[1] = command
;
1010 for (i
= 0; i
< pmdata
.data
[2]; i
++)
1011 packet
.data
[i
+2] = pmdata
.data
[i
+3];
1012 packet
.saveBuf
= adbBuffer
;
1013 packet
.compRout
= adbCompRout
;
1014 packet
.compData
= adbCompData
;
1015 packet
.cmd
= command
;
1017 packet
.ack_only
= 1;
1019 adb_pass_up(&packet
);
1023 rval
= pmgrop(&pmdata
);
1030 adbWaitingCmd
= command
;
1032 PM_VIA_INTR_ENABLE();
1034 /* wait until the PM interrupt has occurred */
1036 while (adbWaiting
== 1) {
1037 switch (mac68k_machine
.machineid
) {
1040 case MACH_MACPB230
: /* daishi tested with Duo230 */
1044 case MACH_MACPB280C
:
1046 case MACH_MACPB190CS
:
1050 if ((via_reg(VIA1
, vIFR
) & 0x10) == 0x10)
1055 (void)intr_dispatch(0x70); /* grab any serial interrupts */
1057 if ((--xdelay
) < 0) {
1063 /* this command enables the interrupt by operating ADB devices */
1064 if (HwCfgFlags3
& 0x00020000) { /* PB Duo series, PB 5XX series */
1065 pmdata
.command
= 0x20;
1066 pmdata
.num_data
= 4;
1067 pmdata
.s_buf
= pmdata
.data
;
1068 pmdata
.r_buf
= pmdata
.data
;
1069 pmdata
.data
[0] = 0x00;
1070 pmdata
.data
[1] = 0x86; /* magic spell for awaking the PM */
1071 pmdata
.data
[2] = 0x00;
1072 pmdata
.data
[3] = 0x0c; /* each bit may express the existent ADB device */
1073 } else { /* PB 1XX series */
1074 pmdata
.command
= 0x20;
1075 pmdata
.num_data
= 3;
1076 pmdata
.s_buf
= pmdata
.data
;
1077 pmdata
.r_buf
= pmdata
.data
;
1078 pmdata
.data
[0] = (u_char
)(command
& 0xf0) | 0xc;
1079 pmdata
.data
[1] = 0x04;
1080 pmdata
.data
[2] = 0x00;
1082 rval
= pmgrop(&pmdata
);
1090 pm_adb_get_TALK_result(PMData
*pmdata
)
1093 struct adbCommand packet
;
1095 /* set up data for adb_pass_up */
1096 packet
.data
[0] = pmdata
->num_data
-1;
1097 packet
.data
[1] = pmdata
->data
[3];
1098 for (i
= 0; i
<packet
.data
[0]-1; i
++)
1099 packet
.data
[i
+2] = pmdata
->data
[i
+4];
1101 packet
.saveBuf
= adbBuffer
;
1102 packet
.compRout
= adbCompRout
;
1103 packet
.compData
= adbCompData
;
1105 packet
.ack_only
= 0;
1107 adb_pass_up(&packet
);
1111 adbBuffer
= (long)0;
1112 adbCompRout
= (long)0;
1113 adbCompData
= (long)0;
1118 pm_adb_get_ADB_data(PMData
*pmdata
)
1121 struct adbCommand packet
;
1123 /* set up data for adb_pass_up */
1124 packet
.data
[0] = pmdata
->num_data
-1; /* number of raw data */
1125 packet
.data
[1] = pmdata
->data
[3]; /* ADB command */
1126 for (i
= 0; i
<packet
.data
[0]-1; i
++)
1127 packet
.data
[i
+2] = pmdata
->data
[i
+4];
1129 packet
.ack_only
= 0;
1130 adb_pass_up(&packet
);
1135 pm_adb_poll_next_device_pm1(PMData
*pmdata
)
1139 u_short bendid
= 0x1;
1143 /* find another existent ADB device to poll */
1144 for (i
= 1; i
< 16; i
++) {
1145 ndid
= (ADB_CMDADDR(pmdata
->data
[3]) + i
) & 0xf;
1147 if ((pm_existent_ADB_devices
& bendid
) != 0)
1151 /* poll the other device */
1152 tmp_pmdata
.command
= 0x20;
1153 tmp_pmdata
.num_data
= 3;
1154 tmp_pmdata
.s_buf
= tmp_pmdata
.data
;
1155 tmp_pmdata
.r_buf
= tmp_pmdata
.data
;
1156 tmp_pmdata
.data
[0] = (u_char
)(ndid
<< 4) | 0xc;
1157 tmp_pmdata
.data
[1] = 0x04; /* magic spell for awaking the PM */
1158 tmp_pmdata
.data
[2] = 0x00;
1159 rval
= pmgrop(&tmp_pmdata
);