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