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