pm_direct.c revision 1.41 1 1.41 nat /* $NetBSD: pm_direct.c,v 1.41 2025/05/06 10:06:01 nat Exp $ */
2 1.1 scottr
3 1.1 scottr /*
4 1.40 nat * Copyright (c) 2024, 2025 Nathanial Sloss <nathanialsloss (at) yahoo.com.au>
5 1.33 nat * All rights reserved.
6 1.33 nat *
7 1.1 scottr * Copyright (C) 1997 Takashi Hamada
8 1.1 scottr * All rights reserved.
9 1.1 scottr *
10 1.1 scottr * Redistribution and use in source and binary forms, with or without
11 1.1 scottr * modification, are permitted provided that the following conditions
12 1.1 scottr * are met:
13 1.1 scottr * 1. Redistributions of source code must retain the above copyright
14 1.1 scottr * notice, this list of conditions and the following disclaimer.
15 1.1 scottr * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 scottr * notice, this list of conditions and the following disclaimer in the
17 1.1 scottr * documentation and/or other materials provided with the distribution.
18 1.1 scottr * 3. All advertising materials mentioning features or use of this software
19 1.1 scottr * must display the following acknowledgement:
20 1.5 scottr * This product includes software developed by Takashi Hamada
21 1.1 scottr * 4. The name of the author may not be used to endorse or promote products
22 1.1 scottr * derived from this software without specific prior written permission.
23 1.1 scottr *
24 1.1 scottr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 1.1 scottr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 1.1 scottr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 1.1 scottr * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 1.1 scottr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 1.1 scottr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 1.1 scottr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 1.1 scottr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 1.1 scottr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 1.1 scottr * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 1.1 scottr */
35 1.5 scottr /* From: pm_direct.c 1.3 03/18/98 Takashi Hamada */
36 1.22 lukem
37 1.22 lukem #include <sys/cdefs.h>
38 1.41 nat __KERNEL_RCSID(0, "$NetBSD: pm_direct.c,v 1.41 2025/05/06 10:06:01 nat Exp $");
39 1.1 scottr
40 1.3 scottr #include "opt_adb.h"
41 1.3 scottr
42 1.3 scottr #ifdef DEBUG
43 1.3 scottr #ifndef ADB_DEBUG
44 1.3 scottr #define ADB_DEBUG
45 1.3 scottr #endif
46 1.3 scottr #endif
47 1.1 scottr
48 1.1 scottr /* #define PM_GRAB_SI 1 */
49 1.1 scottr
50 1.1 scottr #include <sys/types.h>
51 1.40 nat #include <sys/kthread.h>
52 1.40 nat #include <sys/proc.h>
53 1.38 nat #include <sys/mutex.h>
54 1.3 scottr #include <sys/systm.h>
55 1.1 scottr
56 1.35 nat #include <dev/sysmon/sysmonvar.h>
57 1.35 nat
58 1.1 scottr #include <machine/viareg.h>
59 1.1 scottr #include <machine/param.h>
60 1.1 scottr #include <machine/cpu.h>
61 1.1 scottr #include <machine/adbsys.h>
62 1.1 scottr
63 1.2 scottr #include <mac68k/mac68k/macrom.h>
64 1.2 scottr #include <mac68k/dev/adbvar.h>
65 1.2 scottr #include <mac68k/dev/pm_direct.h>
66 1.1 scottr
67 1.1 scottr /* hardware dependent values */
68 1.1 scottr extern u_short ADBDelay;
69 1.1 scottr extern u_int32_t HwCfgFlags3;
70 1.1 scottr extern struct mac68k_machine_S mac68k_machine;
71 1.1 scottr
72 1.1 scottr
73 1.1 scottr /* define the types of the Power Manager */
74 1.1 scottr #define PM_HW_UNKNOWN 0x00 /* don't know */
75 1.1 scottr #define PM_HW_PB1XX 0x01 /* PowerBook 1XX series */
76 1.1 scottr #define PM_HW_PB5XX 0x02 /* PowerBook Duo and 5XX series */
77 1.1 scottr
78 1.1 scottr /* useful macros */
79 1.1 scottr #define PM_SR() via_reg(VIA1, vSR)
80 1.1 scottr #define PM_VIA_INTR_ENABLE() via_reg(VIA1, vIER) = 0x90
81 1.1 scottr #define PM_VIA_INTR_DISABLE() via_reg(VIA1, vIER) = 0x10
82 1.1 scottr #define PM_VIA_CLR_INTR() via_reg(VIA1, vIFR) = 0x90
83 1.1 scottr #define PM_SET_STATE_ACKON() via_reg(VIA2, vBufB) |= 0x04
84 1.1 scottr #define PM_SET_STATE_ACKOFF() via_reg(VIA2, vBufB) &= ~0x04
85 1.4 scottr #define PM_IS_ON (0x02 == (via_reg(VIA2, vBufB) & 0x02))
86 1.4 scottr #define PM_IS_OFF (0x00 == (via_reg(VIA2, vBufB) & 0x02))
87 1.1 scottr
88 1.4 scottr /*
89 1.4 scottr * Variables for internal use
90 1.1 scottr */
91 1.1 scottr int pmHardware = PM_HW_UNKNOWN;
92 1.1 scottr u_short pm_existent_ADB_devices = 0x0; /* each bit expresses the existent ADB device */
93 1.1 scottr u_int pm_LCD_brightness = 0x0;
94 1.1 scottr u_int pm_LCD_contrast = 0x0;
95 1.1 scottr u_int pm_counter = 0; /* clock count */
96 1.35 nat struct sysmon_pswitch pbutton;
97 1.1 scottr
98 1.1 scottr /* these values shows that number of data returned after 'send' cmd is sent */
99 1.1 scottr char pm_send_cmd_type[] = {
100 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
102 1.4 scottr 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
103 1.4 scottr 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
104 1.4 scottr 0xff, 0x00, 0x02, 0x01, 0x01, 0xff, 0xff, 0xff,
105 1.4 scottr 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 1.4 scottr 0x04, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107 1.4 scottr 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff,
108 1.4 scottr 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109 1.4 scottr 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
110 1.4 scottr 0x01, 0x00, 0x02, 0x02, 0xff, 0x01, 0x03, 0x01,
111 1.4 scottr 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
112 1.4 scottr 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
113 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
114 1.4 scottr 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
115 1.4 scottr 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x04, 0x04,
116 1.4 scottr 0x04, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
117 1.4 scottr 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
118 1.4 scottr 0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
119 1.4 scottr 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
120 1.4 scottr 0x02, 0x02, 0x02, 0x04, 0xff, 0x00, 0xff, 0xff,
121 1.4 scottr 0x01, 0x01, 0x03, 0x02, 0xff, 0xff, 0xff, 0xff,
122 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
123 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
124 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
125 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
126 1.4 scottr 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
127 1.4 scottr 0x01, 0x01, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
128 1.4 scottr 0xff, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
129 1.4 scottr 0x03, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
130 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
132 1.1 scottr };
133 1.1 scottr
134 1.1 scottr /* these values shows that number of data returned after 'receive' cmd is sent */
135 1.1 scottr char pm_receive_cmd_type[] = {
136 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
138 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 1.4 scottr 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
140 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
142 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 1.4 scottr 0x05, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
144 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 1.4 scottr 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 1.4 scottr 0x02, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff,
148 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 1.4 scottr 0x04, 0x04, 0x03, 0x09, 0xff, 0xff, 0xff, 0xff,
150 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x01,
152 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 1.4 scottr 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
154 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 1.4 scottr 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
156 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 1.4 scottr 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
158 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
160 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
162 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 1.4 scottr 0x02, 0x02, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff,
164 1.4 scottr 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
165 1.4 scottr 0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00,
166 1.4 scottr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 1.4 scottr 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
168 1.1 scottr };
169 1.1 scottr
170 1.1 scottr
171 1.38 nat /* Spin mutex to seriaize powermanager requests. */
172 1.38 nat kmutex_t pm_mutex;
173 1.38 nat
174 1.1 scottr /*
175 1.1 scottr * Define the private functions
176 1.1 scottr */
177 1.1 scottr
178 1.1 scottr /* for debugging */
179 1.3 scottr #ifdef ADB_DEBUG
180 1.25 christos void pm_printerr(const char *, int, int, char *);
181 1.1 scottr #endif
182 1.1 scottr
183 1.23 chs int pm_wait_busy(int);
184 1.23 chs int pm_wait_free(int);
185 1.1 scottr
186 1.1 scottr /* these functions are for the PB1XX series */
187 1.23 chs int pm_receive_pm1(u_char *);
188 1.23 chs int pm_send_pm1(u_char, int);
189 1.23 chs int pm_pmgrop_pm1(PMData *);
190 1.23 chs void pm_intr_pm1(void *);
191 1.40 nat void brightness_slider(void *); /* brightness slider thread */
192 1.1 scottr
193 1.1 scottr /* these functions are for the PB Duo series and the PB 5XX series */
194 1.23 chs int pm_receive_pm2(u_char *);
195 1.23 chs int pm_send_pm2(u_char);
196 1.23 chs int pm_pmgrop_pm2(PMData *);
197 1.23 chs void pm_intr_pm2(void *);
198 1.1 scottr
199 1.1 scottr /* this function is MRG-Based (for testing) */
200 1.23 chs int pm_pmgrop_mrg(PMData *);
201 1.1 scottr
202 1.1 scottr /* these functions are called from adb_direct.c */
203 1.23 chs void pm_setup_adb(void);
204 1.23 chs void pm_check_adb_devices(int);
205 1.23 chs void pm_intr(void *);
206 1.23 chs int pm_adb_op(u_char *, void *, void *, int);
207 1.23 chs void pm_hw_setup(void);
208 1.1 scottr
209 1.1 scottr /* these functions also use the variables of adb_direct.c */
210 1.23 chs void pm_adb_get_TALK_result(PMData *);
211 1.23 chs void pm_adb_get_ADB_data(PMData *);
212 1.23 chs void pm_adb_poll_next_device_pm1(PMData *);
213 1.1 scottr
214 1.1 scottr
215 1.1 scottr /*
216 1.1 scottr * These variables are in adb_direct.c.
217 1.1 scottr */
218 1.1 scottr extern u_char *adbBuffer; /* pointer to user data area */
219 1.1 scottr extern void *adbCompRout; /* pointer to the completion routine */
220 1.1 scottr extern void *adbCompData; /* pointer to the completion routine data */
221 1.1 scottr extern int adbWaiting; /* waiting for return data from the device */
222 1.1 scottr extern int adbWaitingCmd; /* ADB command we are waiting for */
223 1.1 scottr extern int adbStarting; /* doing ADB reinit, so do "polling" differently */
224 1.1 scottr
225 1.5 scottr #define ADB_MAX_MSG_LENGTH 16
226 1.5 scottr #define ADB_MAX_HDR_LENGTH 8
227 1.5 scottr struct adbCommand {
228 1.5 scottr u_char header[ADB_MAX_HDR_LENGTH]; /* not used yet */
229 1.5 scottr u_char data[ADB_MAX_MSG_LENGTH]; /* packet data only */
230 1.5 scottr u_char *saveBuf; /* where to save result */
231 1.5 scottr u_char *compRout; /* completion routine pointer */
232 1.5 scottr u_char *compData; /* completion routine data pointer */
233 1.5 scottr u_int cmd; /* the original command for this data */
234 1.5 scottr u_int unsol; /* 1 if packet was unsolicited */
235 1.5 scottr u_int ack_only; /* 1 for no special processing */
236 1.5 scottr };
237 1.23 chs extern void adb_pass_up(struct adbCommand *);
238 1.5 scottr
239 1.3 scottr #ifdef ADB_DEBUG
240 1.1 scottr /*
241 1.1 scottr * This function dumps contents of the PMData
242 1.1 scottr */
243 1.1 scottr void
244 1.25 christos pm_printerr(const char *ttl, int rval, int num, char *data)
245 1.1 scottr {
246 1.1 scottr int i;
247 1.1 scottr
248 1.4 scottr printf("pm: %s:%04x %02x ", ttl, rval, num);
249 1.4 scottr for (i = 0; i < num; i++)
250 1.4 scottr printf("%02x ", data[i]);
251 1.4 scottr printf("\n");
252 1.1 scottr }
253 1.1 scottr #endif
254 1.1 scottr
255 1.1 scottr
256 1.1 scottr
257 1.1 scottr /*
258 1.1 scottr * Check the hardware type of the Power Manager
259 1.1 scottr */
260 1.1 scottr void
261 1.23 chs pm_setup_adb(void)
262 1.1 scottr {
263 1.38 nat mutex_init(&pm_mutex, MUTEX_DEFAULT, IPL_HIGH);
264 1.1 scottr switch (mac68k_machine.machineid) {
265 1.1 scottr case MACH_MACPB140:
266 1.1 scottr case MACH_MACPB145:
267 1.1 scottr case MACH_MACPB160:
268 1.1 scottr case MACH_MACPB165:
269 1.1 scottr case MACH_MACPB165C:
270 1.1 scottr case MACH_MACPB170:
271 1.1 scottr case MACH_MACPB180:
272 1.1 scottr case MACH_MACPB180C:
273 1.1 scottr pmHardware = PM_HW_PB1XX;
274 1.35 nat
275 1.35 nat memset(&pbutton, 0, sizeof(struct sysmon_pswitch));
276 1.35 nat pbutton.smpsw_name = "PB";
277 1.35 nat pbutton.smpsw_type = PSWITCH_TYPE_POWER;
278 1.35 nat if (sysmon_pswitch_register(&pbutton) != 0)
279 1.35 nat printf("Unable to register soft power\n");
280 1.40 nat kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
281 1.40 nat brightness_slider, NULL, NULL, "britethrd");
282 1.1 scottr break;
283 1.19 shiba case MACH_MACPB150:
284 1.1 scottr case MACH_MACPB210:
285 1.1 scottr case MACH_MACPB230:
286 1.1 scottr case MACH_MACPB250:
287 1.1 scottr case MACH_MACPB270:
288 1.1 scottr case MACH_MACPB280:
289 1.1 scottr case MACH_MACPB280C:
290 1.1 scottr case MACH_MACPB500:
291 1.21 shiba case MACH_MACPB190:
292 1.21 shiba case MACH_MACPB190CS:
293 1.1 scottr pmHardware = PM_HW_PB5XX;
294 1.35 nat #if notyet
295 1.35 nat memset(&pbutton, 0, sizeof(struct sysmon_pswitch));
296 1.35 nat pbutton.smpsw_name = "PB";
297 1.35 nat pbutton.smpsw_type = PSWITCH_TYPE_POWER;
298 1.35 nat if (sysmon_pswitch_register(&pbutton) != 0)
299 1.35 nat printf("Unable to register soft power\n");
300 1.35 nat #endif
301 1.1 scottr break;
302 1.1 scottr default:
303 1.1 scottr break;
304 1.1 scottr }
305 1.1 scottr }
306 1.1 scottr
307 1.1 scottr
308 1.1 scottr /*
309 1.1 scottr * Check the existent ADB devices
310 1.1 scottr */
311 1.1 scottr void
312 1.23 chs pm_check_adb_devices(int id)
313 1.1 scottr {
314 1.1 scottr u_short ed = 0x1;
315 1.1 scottr
316 1.1 scottr ed <<= id;
317 1.1 scottr pm_existent_ADB_devices |= ed;
318 1.1 scottr }
319 1.1 scottr
320 1.1 scottr
321 1.1 scottr /*
322 1.1 scottr * Wait until PM IC is busy
323 1.1 scottr */
324 1.1 scottr int
325 1.24 jmc pm_wait_busy(int xdelay)
326 1.1 scottr {
327 1.4 scottr while (PM_IS_ON) {
328 1.1 scottr #ifdef PM_GRAB_SI
329 1.15 scottr (void)intr_dispatch(0x70); /* grab any serial interrupts */
330 1.1 scottr #endif
331 1.24 jmc if ((--xdelay) < 0)
332 1.5 scottr return 1; /* timeout */
333 1.1 scottr }
334 1.5 scottr return 0;
335 1.1 scottr }
336 1.1 scottr
337 1.1 scottr
338 1.1 scottr /*
339 1.1 scottr * Wait until PM IC is free
340 1.1 scottr */
341 1.1 scottr int
342 1.24 jmc pm_wait_free(int xdelay)
343 1.1 scottr {
344 1.4 scottr while (PM_IS_OFF) {
345 1.1 scottr #ifdef PM_GRAB_SI
346 1.15 scottr (void)intr_dispatch(0x70); /* grab any serial interrupts */
347 1.1 scottr #endif
348 1.24 jmc if ((--xdelay) < 0)
349 1.5 scottr return 0; /* timeout */
350 1.1 scottr }
351 1.5 scottr return 1;
352 1.1 scottr }
353 1.1 scottr
354 1.1 scottr
355 1.1 scottr
356 1.1 scottr /*
357 1.1 scottr * Functions for the PB1XX series
358 1.1 scottr */
359 1.1 scottr
360 1.1 scottr /*
361 1.1 scottr * Receive data from PM for the PB1XX series
362 1.1 scottr */
363 1.1 scottr int
364 1.23 chs pm_receive_pm1(u_char *data)
365 1.1 scottr {
366 1.1 scottr int rval = 0xffffcd34;
367 1.1 scottr
368 1.1 scottr via_reg(VIA2, vDirA) = 0x00;
369 1.1 scottr
370 1.4 scottr switch (1) {
371 1.1 scottr default:
372 1.4 scottr if (pm_wait_busy(0x40) != 0)
373 1.1 scottr break; /* timeout */
374 1.1 scottr
375 1.1 scottr PM_SET_STATE_ACKOFF();
376 1.1 scottr *data = via_reg(VIA2, 0x200);
377 1.1 scottr
378 1.1 scottr rval = 0xffffcd33;
379 1.4 scottr if (pm_wait_free(0x40) == 0)
380 1.1 scottr break; /* timeout */
381 1.1 scottr
382 1.1 scottr rval = 0x00;
383 1.1 scottr break;
384 1.1 scottr }
385 1.1 scottr
386 1.1 scottr PM_SET_STATE_ACKON();
387 1.1 scottr via_reg(VIA2, vDirA) = 0x00;
388 1.1 scottr
389 1.5 scottr return rval;
390 1.1 scottr }
391 1.1 scottr
392 1.1 scottr
393 1.1 scottr
394 1.1 scottr /*
395 1.1 scottr * Send data to PM for the PB1XX series
396 1.1 scottr */
397 1.1 scottr int
398 1.23 chs pm_send_pm1(u_char data, int timo)
399 1.1 scottr {
400 1.4 scottr int rval;
401 1.1 scottr
402 1.1 scottr via_reg(VIA2, vDirA) = 0xff;
403 1.1 scottr via_reg(VIA2, 0x200) = data;
404 1.1 scottr
405 1.1 scottr PM_SET_STATE_ACKOFF();
406 1.14 scottr #if 0
407 1.14 scottr if (pm_wait_busy(0x400) == 0) {
408 1.14 scottr #else
409 1.14 scottr if (pm_wait_busy(timo) == 0) {
410 1.14 scottr #endif
411 1.1 scottr PM_SET_STATE_ACKON();
412 1.14 scottr if (pm_wait_free(0x40) != 0)
413 1.14 scottr rval = 0x0;
414 1.14 scottr else
415 1.14 scottr rval = 0xffffcd35;
416 1.14 scottr } else {
417 1.14 scottr rval = 0xffffcd36;
418 1.1 scottr }
419 1.1 scottr
420 1.1 scottr PM_SET_STATE_ACKON();
421 1.1 scottr via_reg(VIA2, vDirA) = 0x00;
422 1.1 scottr
423 1.5 scottr return rval;
424 1.1 scottr }
425 1.1 scottr
426 1.1 scottr
427 1.1 scottr /*
428 1.1 scottr * My PMgrOp routine for the PB1XX series
429 1.1 scottr */
430 1.1 scottr int
431 1.23 chs pm_pmgrop_pm1(PMData *pmdata)
432 1.1 scottr {
433 1.4 scottr int i;
434 1.4 scottr int s = 0x81815963;
435 1.4 scottr u_char via1_vIER, via1_vDirA;
436 1.4 scottr int rval = 0;
437 1.4 scottr int num_pm_data = 0;
438 1.36 riastrad u_char pm_cmd;
439 1.4 scottr u_char pm_data;
440 1.4 scottr u_char *pm_buf;
441 1.1 scottr
442 1.38 nat mutex_spin_enter(&pm_mutex);
443 1.38 nat
444 1.32 andvar /* disable all interrupts but PM */
445 1.1 scottr via1_vIER = via_reg(VIA1, vIER);
446 1.1 scottr PM_VIA_INTR_DISABLE();
447 1.1 scottr
448 1.1 scottr via1_vDirA = via_reg(VIA1, vDirA);
449 1.1 scottr
450 1.4 scottr switch (pmdata->command) {
451 1.1 scottr default:
452 1.4 scottr for (i = 0; i < 7; i++) {
453 1.36 riastrad via_reg(VIA2, vDirA) = 0x00;
454 1.1 scottr
455 1.1 scottr /* wait until PM is free */
456 1.4 scottr if (pm_wait_free(ADBDelay) == 0) { /* timeout */
457 1.1 scottr via_reg(VIA2, vDirA) = 0x00;
458 1.1 scottr /* restore formar value */
459 1.1 scottr via_reg(VIA1, vDirA) = via1_vDirA;
460 1.1 scottr via_reg(VIA1, vIER) = via1_vIER;
461 1.38 nat mutex_spin_exit(&pm_mutex);
462 1.5 scottr return 0xffffcd38;
463 1.1 scottr }
464 1.1 scottr
465 1.4 scottr switch (mac68k_machine.machineid) {
466 1.1 scottr case MACH_MACPB160:
467 1.1 scottr case MACH_MACPB165:
468 1.1 scottr case MACH_MACPB165C:
469 1.8 scottr case MACH_MACPB170:
470 1.1 scottr case MACH_MACPB180:
471 1.1 scottr case MACH_MACPB180C:
472 1.1 scottr {
473 1.24 jmc int xdelay = ADBDelay * 16;
474 1.1 scottr
475 1.1 scottr via_reg(VIA2, vDirA) = 0x00;
476 1.24 jmc while ((via_reg(VIA2, 0x200) == 0x7f) && (xdelay >= 0))
477 1.24 jmc xdelay--;
478 1.1 scottr
479 1.24 jmc if (xdelay < 0) { /* timeout */
480 1.1 scottr via_reg(VIA2, vDirA) = 0x00;
481 1.1 scottr /* restore formar value */
482 1.1 scottr via_reg(VIA1, vIER) = via1_vIER;
483 1.38 nat mutex_spin_exit(&pm_mutex);
484 1.5 scottr return 0xffffcd38;
485 1.1 scottr }
486 1.1 scottr }
487 1.1 scottr } /* end switch */
488 1.1 scottr
489 1.4 scottr s = splhigh();
490 1.1 scottr
491 1.1 scottr via1_vDirA = via_reg(VIA1, vDirA);
492 1.1 scottr via_reg(VIA1, vDirA) &= 0x7f;
493 1.1 scottr
494 1.1 scottr pm_cmd = (u_char)(pmdata->command & 0xff);
495 1.4 scottr if ((rval = pm_send_pm1(pm_cmd, ADBDelay * 8)) == 0)
496 1.4 scottr break; /* send command succeeded */
497 1.1 scottr
498 1.1 scottr via_reg(VIA1, vDirA) = via1_vDirA;
499 1.1 scottr splx(s);
500 1.1 scottr } /* end for */
501 1.1 scottr
502 1.1 scottr /* failed to send a command */
503 1.1 scottr if (i == 7) {
504 1.1 scottr via_reg(VIA2, vDirA) = 0x00;
505 1.1 scottr /* restore formar value */
506 1.1 scottr via_reg(VIA1, vDirA) = via1_vDirA;
507 1.1 scottr via_reg(VIA1, vIER) = via1_vIER;
508 1.13 scottr if (s != 0x81815963)
509 1.13 scottr splx(s);
510 1.38 nat mutex_spin_exit(&pm_mutex);
511 1.13 scottr return 0xffffcd38;
512 1.1 scottr }
513 1.1 scottr
514 1.1 scottr /* send # of PM data */
515 1.1 scottr num_pm_data = pmdata->num_data;
516 1.4 scottr if ((rval = pm_send_pm1((u_char)(num_pm_data & 0xff), ADBDelay * 8)) != 0)
517 1.1 scottr break; /* timeout */
518 1.1 scottr
519 1.1 scottr /* send PM data */
520 1.1 scottr pm_buf = (u_char *)pmdata->s_buf;
521 1.4 scottr for (i = 0; i < num_pm_data; i++)
522 1.4 scottr if ((rval = pm_send_pm1(pm_buf[i], ADBDelay * 8)) != 0)
523 1.4 scottr break; /* timeout */
524 1.1 scottr if ((i != num_pm_data) && (num_pm_data != 0))
525 1.4 scottr break; /* timeout */
526 1.1 scottr
527 1.1 scottr /* Will PM IC return data? */
528 1.1 scottr if ((pm_cmd & 0x08) == 0) {
529 1.1 scottr rval = 0;
530 1.4 scottr break; /* no returned data */
531 1.1 scottr }
532 1.1 scottr
533 1.1 scottr rval = 0xffffcd37;
534 1.4 scottr if (pm_wait_busy(ADBDelay) != 0)
535 1.1 scottr break; /* timeout */
536 1.1 scottr
537 1.1 scottr /* receive PM command */
538 1.4 scottr if ((rval = pm_receive_pm1(&pm_data)) != 0)
539 1.1 scottr break;
540 1.1 scottr
541 1.1 scottr pmdata->command = pm_data;
542 1.1 scottr
543 1.1 scottr /* receive number of PM data */
544 1.4 scottr if ((rval = pm_receive_pm1(&pm_data)) != 0)
545 1.4 scottr break; /* timeout */
546 1.1 scottr num_pm_data = pm_data;
547 1.1 scottr pmdata->num_data = num_pm_data;
548 1.1 scottr
549 1.1 scottr /* receive PM data */
550 1.1 scottr pm_buf = (u_char *)pmdata->r_buf;
551 1.4 scottr for (i = 0; i < num_pm_data; i++) {
552 1.4 scottr if ((rval = pm_receive_pm1(&pm_data)) != 0)
553 1.12 scottr break; /* timeout */
554 1.1 scottr pm_buf[i] = pm_data;
555 1.1 scottr }
556 1.1 scottr
557 1.1 scottr rval = 0;
558 1.1 scottr }
559 1.1 scottr
560 1.36 riastrad via_reg(VIA2, vDirA) = 0x00;
561 1.1 scottr
562 1.1 scottr /* restore formar value */
563 1.1 scottr via_reg(VIA1, vDirA) = via1_vDirA;
564 1.1 scottr via_reg(VIA1, vIER) = via1_vIER;
565 1.1 scottr if (s != 0x81815963)
566 1.1 scottr splx(s);
567 1.1 scottr
568 1.38 nat mutex_spin_exit(&pm_mutex);
569 1.38 nat
570 1.5 scottr return rval;
571 1.1 scottr }
572 1.1 scottr
573 1.1 scottr
574 1.1 scottr /*
575 1.5 scottr * My PM interrupt routine for PB1XX series
576 1.1 scottr */
577 1.1 scottr void
578 1.23 chs pm_intr_pm1(void *arg)
579 1.1 scottr {
580 1.4 scottr int s;
581 1.4 scottr int rval;
582 1.4 scottr PMData pmdata;
583 1.1 scottr
584 1.1 scottr s = splhigh();
585 1.1 scottr
586 1.1 scottr PM_VIA_CLR_INTR(); /* clear VIA1 interrupt */
587 1.1 scottr
588 1.30 andvar /* ask PM what happened */
589 1.1 scottr pmdata.command = 0x78;
590 1.1 scottr pmdata.num_data = 0;
591 1.1 scottr pmdata.data[0] = pmdata.data[1] = 0;
592 1.1 scottr pmdata.s_buf = &pmdata.data[2];
593 1.1 scottr pmdata.r_buf = &pmdata.data[2];
594 1.4 scottr rval = pm_pmgrop_pm1(&pmdata);
595 1.1 scottr if (rval != 0) {
596 1.3 scottr #ifdef ADB_DEBUG
597 1.3 scottr if (adb_debug)
598 1.3 scottr printf("pm: PM is not ready. error code=%08x\n", rval);
599 1.1 scottr #endif
600 1.1 scottr splx(s);
601 1.31 nat return;
602 1.1 scottr }
603 1.1 scottr
604 1.1 scottr if ((pmdata.data[2] & 0x10) == 0x10) {
605 1.4 scottr if ((pmdata.data[2] & 0x0f) == 0) {
606 1.4 scottr /* ADB data that were requested by TALK command */
607 1.1 scottr pm_adb_get_TALK_result(&pmdata);
608 1.4 scottr } else if ((pmdata.data[2] & 0x08) == 0x8) {
609 1.4 scottr /* PM is requesting to poll */
610 1.1 scottr pm_adb_poll_next_device_pm1(&pmdata);
611 1.4 scottr } else if ((pmdata.data[2] & 0x04) == 0x4) {
612 1.4 scottr /* ADB device event */
613 1.1 scottr pm_adb_get_ADB_data(&pmdata);
614 1.1 scottr }
615 1.35 nat } else if ((pmdata.num_data == 0x1) && (pmdata.data[0] == 0)) {
616 1.35 nat /* PowerBook 160/180 Power button. */
617 1.35 nat sysmon_pswitch_event(&pbutton, PSWITCH_EVENT_PRESSED);
618 1.1 scottr } else {
619 1.3 scottr #ifdef ADB_DEBUG
620 1.3 scottr if (adb_debug)
621 1.3 scottr pm_printerr("driver does not supported this event.",
622 1.3 scottr rval, pmdata.num_data, pmdata.data);
623 1.1 scottr #endif
624 1.1 scottr }
625 1.1 scottr
626 1.1 scottr splx(s);
627 1.1 scottr }
628 1.1 scottr
629 1.40 nat void
630 1.40 nat brightness_slider(void *arg)
631 1.40 nat {
632 1.40 nat int s;
633 1.40 nat int rval;
634 1.40 nat PMData pmdata;
635 1.40 nat
636 1.40 nat for (;;) {
637 1.41 nat kpause("brslider", false, hz / 4, NULL);
638 1.40 nat
639 1.40 nat s = splhigh();
640 1.40 nat
641 1.40 nat pmdata.command = 0x49;
642 1.40 nat pmdata.num_data = 0;
643 1.40 nat pmdata.data[0] = pmdata.data[1] = 0;
644 1.40 nat pmdata.s_buf = &pmdata.data[0];
645 1.40 nat pmdata.r_buf = &pmdata.data[0];
646 1.40 nat rval = pm_pmgrop_pm1(&pmdata);
647 1.40 nat if (rval != 0) {
648 1.40 nat #ifdef ADB_DEBUG
649 1.40 nat if (adb_debug) {
650 1.40 nat printf("pm: PM is not ready. "
651 1.40 nat "error code=%08x\n", rval);
652 1.40 nat }
653 1.40 nat #endif
654 1.40 nat splx(s);
655 1.40 nat continue;
656 1.40 nat }
657 1.1 scottr
658 1.40 nat if (((uint8_t)pmdata.data[0] / 8) != pm_LCD_brightness) {
659 1.40 nat pm_LCD_brightness = (uint8_t)pmdata.data[0] / 8;
660 1.40 nat pm_LCD_brightness =
661 1.40 nat pm_set_brightness(pm_LCD_brightness);
662 1.40 nat }
663 1.40 nat
664 1.40 nat splx(s);
665 1.40 nat }
666 1.40 nat }
667 1.1 scottr
668 1.1 scottr /*
669 1.1 scottr * Functions for the PB Duo series and the PB 5XX series
670 1.1 scottr */
671 1.1 scottr
672 1.1 scottr /*
673 1.1 scottr * Receive data from PM for the PB Duo series and the PB 5XX series
674 1.1 scottr */
675 1.1 scottr int
676 1.23 chs pm_receive_pm2(u_char *data)
677 1.1 scottr {
678 1.4 scottr int rval;
679 1.1 scottr
680 1.1 scottr rval = 0xffffcd34;
681 1.1 scottr
682 1.4 scottr switch (1) {
683 1.1 scottr default:
684 1.1 scottr /* set VIA SR to input mode */
685 1.1 scottr via_reg(VIA1, vACR) |= 0x0c;
686 1.1 scottr via_reg(VIA1, vACR) &= ~0x10;
687 1.29 martin PM_SR();
688 1.1 scottr
689 1.1 scottr PM_SET_STATE_ACKOFF();
690 1.1 scottr if (pm_wait_busy((int)ADBDelay*32) != 0)
691 1.1 scottr break; /* timeout */
692 1.1 scottr
693 1.1 scottr PM_SET_STATE_ACKON();
694 1.1 scottr rval = 0xffffcd33;
695 1.1 scottr if (pm_wait_free((int)ADBDelay*32) == 0)
696 1.1 scottr break; /* timeout */
697 1.1 scottr
698 1.1 scottr *data = PM_SR();
699 1.1 scottr rval = 0;
700 1.1 scottr
701 1.1 scottr break;
702 1.1 scottr }
703 1.1 scottr
704 1.1 scottr PM_SET_STATE_ACKON();
705 1.1 scottr via_reg(VIA1, vACR) |= 0x1c;
706 1.1 scottr
707 1.5 scottr return rval;
708 1.36 riastrad }
709 1.1 scottr
710 1.1 scottr
711 1.1 scottr
712 1.1 scottr /*
713 1.1 scottr * Send data to PM for the PB Duo series and the PB 5XX series
714 1.1 scottr */
715 1.1 scottr int
716 1.23 chs pm_send_pm2(u_char data)
717 1.1 scottr {
718 1.4 scottr int rval;
719 1.1 scottr
720 1.1 scottr via_reg(VIA1, vACR) |= 0x1c;
721 1.1 scottr PM_SR() = data;
722 1.1 scottr
723 1.1 scottr PM_SET_STATE_ACKOFF();
724 1.14 scottr if (pm_wait_busy((int)ADBDelay*32) == 0) {
725 1.1 scottr PM_SET_STATE_ACKON();
726 1.14 scottr if (pm_wait_free((int)ADBDelay*32) != 0)
727 1.14 scottr rval = 0;
728 1.14 scottr else
729 1.14 scottr rval = 0xffffcd35;
730 1.14 scottr } else {
731 1.14 scottr rval = 0xffffcd36;
732 1.1 scottr }
733 1.1 scottr
734 1.1 scottr PM_SET_STATE_ACKON();
735 1.1 scottr via_reg(VIA1, vACR) |= 0x1c;
736 1.1 scottr
737 1.5 scottr return rval;
738 1.1 scottr }
739 1.1 scottr
740 1.1 scottr
741 1.1 scottr
742 1.1 scottr /*
743 1.1 scottr * My PMgrOp routine for the PB Duo series and the PB 5XX series
744 1.1 scottr */
745 1.1 scottr int
746 1.23 chs pm_pmgrop_pm2(PMData *pmdata)
747 1.1 scottr {
748 1.4 scottr int i;
749 1.4 scottr int s;
750 1.4 scottr u_char via1_vIER;
751 1.4 scottr int rval = 0;
752 1.4 scottr int num_pm_data = 0;
753 1.36 riastrad u_char pm_cmd;
754 1.4 scottr short pm_num_rx_data;
755 1.4 scottr u_char pm_data;
756 1.4 scottr u_char *pm_buf;
757 1.1 scottr
758 1.38 nat mutex_spin_enter(&pm_mutex);
759 1.4 scottr s = splhigh();
760 1.1 scottr
761 1.32 andvar /* disable all interrupts but PM */
762 1.1 scottr via1_vIER = 0x10;
763 1.1 scottr via1_vIER &= via_reg(VIA1, vIER);
764 1.1 scottr via_reg(VIA1, vIER) = via1_vIER;
765 1.1 scottr if (via1_vIER != 0x0)
766 1.1 scottr via1_vIER |= 0x80;
767 1.1 scottr
768 1.4 scottr switch (pmdata->command) {
769 1.1 scottr default:
770 1.1 scottr /* wait until PM is free */
771 1.1 scottr pm_cmd = (u_char)(pmdata->command & 0xff);
772 1.1 scottr rval = 0xcd38;
773 1.4 scottr if (pm_wait_free(ADBDelay * 4) == 0)
774 1.1 scottr break; /* timeout */
775 1.1 scottr
776 1.36 riastrad if (HwCfgFlags3 & 0x00200000) {
777 1.4 scottr /* PB 160, PB 165(c), PB 180(c)? */
778 1.24 jmc int xdelay = ADBDelay * 16;
779 1.1 scottr
780 1.1 scottr via_reg(VIA2, vDirA) = 0x00;
781 1.4 scottr while ((via_reg(VIA2, 0x200) == 0x07) &&
782 1.24 jmc (xdelay >= 0))
783 1.24 jmc xdelay--;
784 1.1 scottr
785 1.24 jmc if (xdelay < 0) {
786 1.1 scottr rval = 0xffffcd38;
787 1.1 scottr break; /* timeout */
788 1.1 scottr }
789 1.1 scottr }
790 1.1 scottr
791 1.1 scottr /* send PM command */
792 1.4 scottr if ((rval = pm_send_pm2((u_char)(pm_cmd & 0xff))))
793 1.1 scottr break; /* timeout */
794 1.1 scottr
795 1.1 scottr /* send number of PM data */
796 1.1 scottr num_pm_data = pmdata->num_data;
797 1.1 scottr if (HwCfgFlags3 & 0x00020000) { /* PB Duo, PB 5XX */
798 1.1 scottr if (pm_send_cmd_type[pm_cmd] < 0) {
799 1.4 scottr if ((rval = pm_send_pm2((u_char)(num_pm_data & 0xff))) != 0)
800 1.1 scottr break; /* timeout */
801 1.1 scottr pmdata->command = 0;
802 1.1 scottr }
803 1.1 scottr } else { /* PB 1XX series ? */
804 1.4 scottr if ((rval = pm_send_pm2((u_char)(num_pm_data & 0xff))) != 0)
805 1.1 scottr break; /* timeout */
806 1.36 riastrad }
807 1.1 scottr /* send PM data */
808 1.1 scottr pm_buf = (u_char *)pmdata->s_buf;
809 1.4 scottr for (i = 0 ; i < num_pm_data; i++)
810 1.4 scottr if ((rval = pm_send_pm2(pm_buf[i])) != 0)
811 1.1 scottr break; /* timeout */
812 1.1 scottr if (i != num_pm_data)
813 1.1 scottr break; /* timeout */
814 1.1 scottr
815 1.1 scottr
816 1.1 scottr /* check if PM will send me data */
817 1.1 scottr pm_num_rx_data = pm_receive_cmd_type[pm_cmd];
818 1.1 scottr pmdata->num_data = pm_num_rx_data;
819 1.1 scottr if (pm_num_rx_data == 0) {
820 1.1 scottr rval = 0;
821 1.1 scottr break; /* no return data */
822 1.1 scottr }
823 1.1 scottr
824 1.1 scottr /* receive PM command */
825 1.1 scottr pm_data = pmdata->command;
826 1.1 scottr if (HwCfgFlags3 & 0x00020000) { /* PB Duo, PB 5XX */
827 1.1 scottr pm_num_rx_data--;
828 1.1 scottr if (pm_num_rx_data == 0)
829 1.4 scottr if ((rval = pm_receive_pm2(&pm_data)) != 0) {
830 1.1 scottr rval = 0xffffcd37;
831 1.1 scottr break;
832 1.1 scottr }
833 1.1 scottr pmdata->command = pm_data;
834 1.1 scottr } else { /* PB 1XX series ? */
835 1.4 scottr if ((rval = pm_receive_pm2(&pm_data)) != 0) {
836 1.1 scottr rval = 0xffffcd37;
837 1.1 scottr break;
838 1.1 scottr }
839 1.1 scottr pmdata->command = pm_data;
840 1.1 scottr }
841 1.1 scottr
842 1.1 scottr /* receive number of PM data */
843 1.1 scottr if (HwCfgFlags3 & 0x00020000) { /* PB Duo, PB 5XX */
844 1.1 scottr if (pm_num_rx_data < 0) {
845 1.4 scottr if ((rval = pm_receive_pm2(&pm_data)) != 0)
846 1.1 scottr break; /* timeout */
847 1.1 scottr num_pm_data = pm_data;
848 1.1 scottr } else
849 1.1 scottr num_pm_data = pm_num_rx_data;
850 1.1 scottr pmdata->num_data = num_pm_data;
851 1.1 scottr } else { /* PB 1XX serias ? */
852 1.4 scottr if ((rval = pm_receive_pm2(&pm_data)) != 0)
853 1.1 scottr break; /* timeout */
854 1.1 scottr num_pm_data = pm_data;
855 1.1 scottr pmdata->num_data = num_pm_data;
856 1.1 scottr }
857 1.1 scottr
858 1.1 scottr /* receive PM data */
859 1.1 scottr pm_buf = (u_char *)pmdata->r_buf;
860 1.4 scottr for (i = 0; i < num_pm_data; i++) {
861 1.4 scottr if ((rval = pm_receive_pm2(&pm_data)) != 0)
862 1.1 scottr break; /* timeout */
863 1.1 scottr pm_buf[i] = pm_data;
864 1.1 scottr }
865 1.1 scottr
866 1.1 scottr rval = 0;
867 1.1 scottr }
868 1.1 scottr
869 1.1 scottr /* restore former value */
870 1.1 scottr via_reg(VIA1, vIER) = via1_vIER;
871 1.1 scottr splx(s);
872 1.1 scottr
873 1.38 nat mutex_spin_exit(&pm_mutex);
874 1.5 scottr return rval;
875 1.1 scottr }
876 1.1 scottr
877 1.1 scottr
878 1.1 scottr /*
879 1.1 scottr * My PM interrupt routine for the PB Duo series and the PB 5XX series
880 1.1 scottr */
881 1.1 scottr void
882 1.23 chs pm_intr_pm2(void *arg)
883 1.1 scottr {
884 1.4 scottr int s;
885 1.4 scottr int rval;
886 1.4 scottr PMData pmdata;
887 1.1 scottr
888 1.1 scottr s = splhigh();
889 1.1 scottr
890 1.4 scottr PM_VIA_CLR_INTR(); /* clear VIA1 interrupt */
891 1.30 andvar /* ask PM what happened */
892 1.1 scottr pmdata.command = 0x78;
893 1.1 scottr pmdata.num_data = 0;
894 1.1 scottr pmdata.s_buf = &pmdata.data[2];
895 1.1 scottr pmdata.r_buf = &pmdata.data[2];
896 1.4 scottr rval = pm_pmgrop_pm2(&pmdata);
897 1.1 scottr if (rval != 0) {
898 1.3 scottr #ifdef ADB_DEBUG
899 1.3 scottr if (adb_debug)
900 1.3 scottr printf("pm: PM is not ready. error code: %08x\n", rval);
901 1.1 scottr #endif
902 1.1 scottr splx(s);
903 1.31 nat return;
904 1.1 scottr }
905 1.1 scottr
906 1.4 scottr switch ((u_int)(pmdata.data[2] & 0xff)) {
907 1.4 scottr case 0x00: /* 1 sec interrupt? */
908 1.1 scottr break;
909 1.4 scottr case 0x80: /* 1 sec interrupt? */
910 1.1 scottr pm_counter++;
911 1.1 scottr break;
912 1.37 nat case 0x08: /* Brightness/Contrast button on LCD panel */
913 1.1 scottr /* get brightness and contrast of the LCD */
914 1.1 scottr pm_LCD_brightness = (u_int)pmdata.data[3] & 0xff;
915 1.1 scottr pm_LCD_contrast = (u_int)pmdata.data[4] & 0xff;
916 1.1 scottr /*
917 1.4 scottr pm_printerr("#08", rval, pmdata.num_data, pmdata.data);
918 1.1 scottr pmdata.command = 0x33;
919 1.1 scottr pmdata.num_data = 1;
920 1.1 scottr pmdata.s_buf = pmdata.data;
921 1.1 scottr pmdata.r_buf = pmdata.data;
922 1.1 scottr pmdata.data[0] = pm_LCD_contrast;
923 1.4 scottr rval = pm_pmgrop_pm2(&pmdata);
924 1.4 scottr pm_printerr("#33", rval, pmdata.num_data, pmdata.data);
925 1.1 scottr */
926 1.33 nat pm_LCD_brightness =
927 1.33 nat pm_set_brightness(pm_LCD_brightness);
928 1.1 scottr break;
929 1.4 scottr case 0x10: /* ADB data that were requested by TALK command */
930 1.1 scottr case 0x14:
931 1.1 scottr pm_adb_get_TALK_result(&pmdata);
932 1.1 scottr break;
933 1.4 scottr case 0x16: /* ADB device event */
934 1.1 scottr case 0x18:
935 1.1 scottr case 0x1e:
936 1.1 scottr pm_adb_get_ADB_data(&pmdata);
937 1.1 scottr break;
938 1.1 scottr default:
939 1.3 scottr #ifdef ADB_DEBUG
940 1.3 scottr if (adb_debug)
941 1.3 scottr pm_printerr("driver does not supported this event.",
942 1.3 scottr pmdata.data[2], pmdata.num_data,
943 1.3 scottr pmdata.data);
944 1.1 scottr #endif
945 1.1 scottr break;
946 1.1 scottr }
947 1.1 scottr
948 1.1 scottr splx(s);
949 1.1 scottr }
950 1.1 scottr
951 1.1 scottr
952 1.1 scottr /*
953 1.1 scottr * MRG-based PMgrOp routine
954 1.1 scottr */
955 1.1 scottr int
956 1.23 chs pm_pmgrop_mrg(PMData *pmdata)
957 1.1 scottr {
958 1.1 scottr u_int32_t rval=0;
959 1.1 scottr
960 1.27 perry __asm volatile(
961 1.20 thorpej " movl %1,%%a0 \n"
962 1.20 thorpej " .word 0xa085 \n"
963 1.20 thorpej " movl %%d0,%0"
964 1.1 scottr : "=g" (rval)
965 1.1 scottr : "g" (pmdata)
966 1.18 chs : "a0","d0");
967 1.1 scottr
968 1.1 scottr return rval;
969 1.1 scottr }
970 1.1 scottr
971 1.1 scottr
972 1.1 scottr /*
973 1.1 scottr * My PMgrOp routine
974 1.1 scottr */
975 1.1 scottr int
976 1.23 chs pmgrop(PMData *pmdata)
977 1.1 scottr {
978 1.4 scottr switch (pmHardware) {
979 1.1 scottr case PM_HW_PB1XX:
980 1.4 scottr return (pm_pmgrop_pm1(pmdata));
981 1.1 scottr break;
982 1.1 scottr case PM_HW_PB5XX:
983 1.4 scottr return (pm_pmgrop_pm2(pmdata));
984 1.1 scottr break;
985 1.1 scottr default:
986 1.4 scottr /* return (pmgrop_mrg(pmdata)); */
987 1.5 scottr return 1;
988 1.1 scottr }
989 1.1 scottr }
990 1.1 scottr
991 1.1 scottr
992 1.1 scottr /*
993 1.1 scottr * My PM interrupt routine
994 1.1 scottr */
995 1.1 scottr void
996 1.23 chs pm_intr(void *arg)
997 1.1 scottr {
998 1.4 scottr switch (pmHardware) {
999 1.1 scottr case PM_HW_PB1XX:
1000 1.9 briggs pm_intr_pm1(arg);
1001 1.1 scottr break;
1002 1.1 scottr case PM_HW_PB5XX:
1003 1.9 briggs pm_intr_pm2(arg);
1004 1.1 scottr break;
1005 1.1 scottr default:
1006 1.1 scottr break;
1007 1.1 scottr }
1008 1.1 scottr }
1009 1.1 scottr
1010 1.1 scottr
1011 1.9 briggs void
1012 1.23 chs pm_hw_setup(void)
1013 1.9 briggs {
1014 1.9 briggs switch (pmHardware) {
1015 1.9 briggs case PM_HW_PB1XX:
1016 1.9 briggs via1_register_irq(4, pm_intr_pm1, (void *)0);
1017 1.9 briggs PM_VIA_CLR_INTR();
1018 1.9 briggs break;
1019 1.9 briggs case PM_HW_PB5XX:
1020 1.9 briggs via1_register_irq(4, pm_intr_pm2, (void *)0);
1021 1.9 briggs PM_VIA_CLR_INTR();
1022 1.9 briggs break;
1023 1.9 briggs default:
1024 1.9 briggs break;
1025 1.9 briggs }
1026 1.9 briggs }
1027 1.9 briggs
1028 1.1 scottr
1029 1.1 scottr /*
1030 1.1 scottr * Synchronous ADBOp routine for the Power Manager
1031 1.1 scottr */
1032 1.1 scottr int
1033 1.23 chs pm_adb_op(u_char *buffer, void *compRout, void *data, int command)
1034 1.1 scottr {
1035 1.5 scottr int i;
1036 1.4 scottr int s;
1037 1.4 scottr int rval;
1038 1.24 jmc int xdelay;
1039 1.4 scottr PMData pmdata;
1040 1.5 scottr struct adbCommand packet;
1041 1.1 scottr
1042 1.1 scottr if (adbWaiting == 1)
1043 1.5 scottr return 1;
1044 1.1 scottr
1045 1.1 scottr s = splhigh();
1046 1.1 scottr via_reg(VIA1, vIER) = 0x10;
1047 1.1 scottr
1048 1.1 scottr adbBuffer = buffer;
1049 1.1 scottr adbCompRout = compRout;
1050 1.1 scottr adbCompData = data;
1051 1.1 scottr
1052 1.1 scottr pmdata.command = 0x20;
1053 1.1 scottr pmdata.s_buf = pmdata.data;
1054 1.1 scottr pmdata.r_buf = pmdata.data;
1055 1.1 scottr
1056 1.1 scottr if ((command & 0xc) == 0x8) { /* if the command is LISTEN, add number of ADB data to number of PM data */
1057 1.1 scottr if (buffer != (u_char *)0)
1058 1.1 scottr pmdata.num_data = buffer[0] + 3;
1059 1.1 scottr } else {
1060 1.1 scottr pmdata.num_data = 3;
1061 1.1 scottr }
1062 1.1 scottr
1063 1.1 scottr pmdata.data[0] = (u_char)(command & 0xff);
1064 1.1 scottr pmdata.data[1] = 0;
1065 1.1 scottr if ((command & 0xc) == 0x8) { /* if the command is LISTEN, copy ADB data to PM buffer */
1066 1.1 scottr if ((buffer != (u_char *)0) && (buffer[0] <= 24)) {
1067 1.1 scottr pmdata.data[2] = buffer[0]; /* number of data */
1068 1.4 scottr for (i = 0; i < buffer[0]; i++)
1069 1.1 scottr pmdata.data[3 + i] = buffer[1 + i];
1070 1.1 scottr } else
1071 1.1 scottr pmdata.data[2] = 0;
1072 1.1 scottr } else
1073 1.1 scottr pmdata.data[2] = 0;
1074 1.1 scottr
1075 1.5 scottr if ((command & 0xc) != 0xc) { /* if the command is not TALK */
1076 1.9 briggs /* set up stuff fNULLor adb_pass_up */
1077 1.5 scottr packet.data[0] = 1 + pmdata.data[2];
1078 1.5 scottr packet.data[1] = command;
1079 1.5 scottr for (i = 0; i < pmdata.data[2]; i++)
1080 1.5 scottr packet.data[i+2] = pmdata.data[i+3];
1081 1.5 scottr packet.saveBuf = adbBuffer;
1082 1.5 scottr packet.compRout = adbCompRout;
1083 1.5 scottr packet.compData = adbCompData;
1084 1.5 scottr packet.cmd = command;
1085 1.5 scottr packet.unsol = 0;
1086 1.5 scottr packet.ack_only = 1;
1087 1.10 scottr adb_polling = 1;
1088 1.5 scottr adb_pass_up(&packet);
1089 1.10 scottr adb_polling = 0;
1090 1.5 scottr }
1091 1.5 scottr
1092 1.4 scottr rval = pmgrop(&pmdata);
1093 1.12 scottr if (rval != 0) {
1094 1.12 scottr splx(s);
1095 1.5 scottr return 1;
1096 1.12 scottr }
1097 1.1 scottr
1098 1.5 scottr adbWaiting = 1;
1099 1.5 scottr adbWaitingCmd = command;
1100 1.1 scottr
1101 1.1 scottr PM_VIA_INTR_ENABLE();
1102 1.1 scottr
1103 1.17 wiz /* wait until the PM interrupt has occurred */
1104 1.24 jmc xdelay = 0x80000;
1105 1.4 scottr while (adbWaiting == 1) {
1106 1.15 scottr switch (mac68k_machine.machineid) {
1107 1.19 shiba case MACH_MACPB150:
1108 1.15 scottr case MACH_MACPB210:
1109 1.15 scottr case MACH_MACPB230: /* daishi tested with Duo230 */
1110 1.15 scottr case MACH_MACPB250:
1111 1.15 scottr case MACH_MACPB270:
1112 1.15 scottr case MACH_MACPB280:
1113 1.15 scottr case MACH_MACPB280C:
1114 1.21 shiba case MACH_MACPB190:
1115 1.21 shiba case MACH_MACPB190CS:
1116 1.9 briggs pm_intr((void *)0);
1117 1.15 scottr break;
1118 1.15 scottr default:
1119 1.15 scottr if ((via_reg(VIA1, vIFR) & 0x10) == 0x10)
1120 1.15 scottr pm_intr((void *)0);
1121 1.15 scottr break;
1122 1.15 scottr }
1123 1.1 scottr #ifdef PM_GRAB_SI
1124 1.15 scottr (void)intr_dispatch(0x70); /* grab any serial interrupts */
1125 1.1 scottr #endif
1126 1.24 jmc if ((--xdelay) < 0) {
1127 1.12 scottr splx(s);
1128 1.5 scottr return 1;
1129 1.12 scottr }
1130 1.1 scottr }
1131 1.1 scottr
1132 1.4 scottr /* this command enables the interrupt by operating ADB devices */
1133 1.5 scottr if (HwCfgFlags3 & 0x00020000) { /* PB Duo series, PB 5XX series */
1134 1.1 scottr pmdata.command = 0x20;
1135 1.1 scottr pmdata.num_data = 4;
1136 1.1 scottr pmdata.s_buf = pmdata.data;
1137 1.1 scottr pmdata.r_buf = pmdata.data;
1138 1.36 riastrad pmdata.data[0] = 0x00;
1139 1.1 scottr pmdata.data[1] = 0x86; /* magic spell for awaking the PM */
1140 1.36 riastrad pmdata.data[2] = 0x00;
1141 1.1 scottr pmdata.data[3] = 0x0c; /* each bit may express the existent ADB device */
1142 1.5 scottr } else { /* PB 1XX series */
1143 1.1 scottr pmdata.command = 0x20;
1144 1.1 scottr pmdata.num_data = 3;
1145 1.1 scottr pmdata.s_buf = pmdata.data;
1146 1.1 scottr pmdata.r_buf = pmdata.data;
1147 1.1 scottr pmdata.data[0] = (u_char)(command & 0xf0) | 0xc;
1148 1.1 scottr pmdata.data[1] = 0x04;
1149 1.1 scottr pmdata.data[2] = 0x00;
1150 1.1 scottr }
1151 1.4 scottr rval = pmgrop(&pmdata);
1152 1.1 scottr
1153 1.1 scottr splx(s);
1154 1.5 scottr return rval;
1155 1.1 scottr }
1156 1.1 scottr
1157 1.1 scottr
1158 1.1 scottr void
1159 1.23 chs pm_adb_get_TALK_result(PMData *pmdata)
1160 1.1 scottr {
1161 1.1 scottr int i;
1162 1.5 scottr struct adbCommand packet;
1163 1.1 scottr
1164 1.5 scottr /* set up data for adb_pass_up */
1165 1.5 scottr packet.data[0] = pmdata->num_data-1;
1166 1.5 scottr packet.data[1] = pmdata->data[3];
1167 1.5 scottr for (i = 0; i <packet.data[0]-1; i++)
1168 1.5 scottr packet.data[i+2] = pmdata->data[i+4];
1169 1.5 scottr
1170 1.5 scottr packet.saveBuf = adbBuffer;
1171 1.5 scottr packet.compRout = adbCompRout;
1172 1.5 scottr packet.compData = adbCompData;
1173 1.5 scottr packet.unsol = 0;
1174 1.5 scottr packet.ack_only = 0;
1175 1.10 scottr adb_polling = 1;
1176 1.5 scottr adb_pass_up(&packet);
1177 1.10 scottr adb_polling = 0;
1178 1.5 scottr
1179 1.5 scottr adbWaiting = 0;
1180 1.5 scottr adbBuffer = (long)0;
1181 1.5 scottr adbCompRout = (long)0;
1182 1.5 scottr adbCompData = (long)0;
1183 1.1 scottr }
1184 1.1 scottr
1185 1.1 scottr
1186 1.1 scottr void
1187 1.23 chs pm_adb_get_ADB_data(PMData *pmdata)
1188 1.1 scottr {
1189 1.1 scottr int i;
1190 1.5 scottr struct adbCommand packet;
1191 1.1 scottr
1192 1.5 scottr /* set up data for adb_pass_up */
1193 1.5 scottr packet.data[0] = pmdata->num_data-1; /* number of raw data */
1194 1.5 scottr packet.data[1] = pmdata->data[3]; /* ADB command */
1195 1.5 scottr for (i = 0; i <packet.data[0]-1; i++)
1196 1.5 scottr packet.data[i+2] = pmdata->data[i+4];
1197 1.5 scottr packet.unsol = 1;
1198 1.5 scottr packet.ack_only = 0;
1199 1.5 scottr adb_pass_up(&packet);
1200 1.1 scottr }
1201 1.1 scottr
1202 1.1 scottr
1203 1.1 scottr void
1204 1.23 chs pm_adb_poll_next_device_pm1(PMData *pmdata)
1205 1.1 scottr {
1206 1.1 scottr int i;
1207 1.1 scottr int ndid;
1208 1.1 scottr u_short bendid = 0x1;
1209 1.1 scottr PMData tmp_pmdata;
1210 1.1 scottr
1211 1.1 scottr /* find another existent ADB device to poll */
1212 1.4 scottr for (i = 1; i < 16; i++) {
1213 1.11 scottr ndid = (ADB_CMDADDR(pmdata->data[3]) + i) & 0xf;
1214 1.1 scottr bendid <<= ndid;
1215 1.1 scottr if ((pm_existent_ADB_devices & bendid) != 0)
1216 1.1 scottr break;
1217 1.1 scottr }
1218 1.1 scottr
1219 1.1 scottr /* poll the other device */
1220 1.1 scottr tmp_pmdata.command = 0x20;
1221 1.1 scottr tmp_pmdata.num_data = 3;
1222 1.1 scottr tmp_pmdata.s_buf = tmp_pmdata.data;
1223 1.1 scottr tmp_pmdata.r_buf = tmp_pmdata.data;
1224 1.1 scottr tmp_pmdata.data[0] = (u_char)(ndid << 4) | 0xc;
1225 1.1 scottr tmp_pmdata.data[1] = 0x04; /* magic spell for awaking the PM */
1226 1.1 scottr tmp_pmdata.data[2] = 0x00;
1227 1.29 martin pmgrop(&tmp_pmdata);
1228 1.1 scottr }
1229 1.34 nat
1230 1.36 riastrad void
1231 1.34 nat pm_poweroff(void)
1232 1.34 nat {
1233 1.34 nat PMData pmdata;
1234 1.34 nat int attempt = 3;
1235 1.34 nat
1236 1.34 nat while (pmHardware == PM_HW_PB1XX && attempt > 0) {
1237 1.39 nat pmdata.command = 0xef;
1238 1.34 nat pmdata.num_data = 0;
1239 1.34 nat pmdata.data[0] = pmdata.data[1] = 0;
1240 1.34 nat pmdata.s_buf = &pmdata.data[2];
1241 1.34 nat pmdata.r_buf = &pmdata.data[2];
1242 1.34 nat (void)pm_pmgrop_pm1(&pmdata);
1243 1.34 nat attempt--;
1244 1.36 riastrad }
1245 1.34 nat
1246 1.34 nat return;
1247 1.34 nat }
1248 1.34 nat
1249 1.33 nat u_int
1250 1.33 nat pm_set_brightness(u_int brightness)
1251 1.33 nat {
1252 1.33 nat PMData pmdata;
1253 1.33 nat
1254 1.33 nat pmdata.num_data = 1;
1255 1.33 nat pmdata.s_buf = pmdata.data;
1256 1.33 nat pmdata.r_buf = pmdata.data;
1257 1.33 nat
1258 1.33 nat switch (pmHardware) {
1259 1.33 nat case PM_HW_PB5XX:
1260 1.33 nat /* this is an experimental code */
1261 1.33 nat pmdata.command = 0x41;
1262 1.37 nat if ((int)brightness < 0)
1263 1.37 nat brightness = 0;
1264 1.37 nat if ((int)brightness > 31)
1265 1.37 nat brightness = 31;
1266 1.37 nat pmdata.data[0] = (31 - brightness) * 23 / 10 + 37;
1267 1.33 nat (void)pm_pmgrop_pm2(&pmdata);
1268 1.33 nat break;
1269 1.33 nat case PM_HW_PB1XX:
1270 1.33 nat /* this is an experimental code also */
1271 1.33 nat pmdata.command = 0x40;
1272 1.33 nat if ((int)brightness < 0)
1273 1.33 nat brightness = 0;
1274 1.33 nat if ((int)brightness > 31)
1275 1.33 nat brightness = 31;
1276 1.33 nat pmdata.data[0] = 31 - brightness;
1277 1.33 nat (void)pm_pmgrop_pm1(&pmdata);
1278 1.33 nat break;
1279 1.33 nat default:
1280 1.33 nat
1281 1.33 nat return 0;
1282 1.33 nat break;
1283 1.33 nat }
1284 1.33 nat
1285 1.33 nat return brightness;
1286 1.33 nat }
1287