pm_direct.c revision 1.8
1/* $NetBSD: pm_direct.c,v 1.8 1999/03/05 06:45:41 scottr 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_MACPB170: 459 case MACH_MACPB180: 460 case MACH_MACPB180C: 461 { 462 int delay = ADBDelay * 16; 463 464 via_reg(VIA2, vDirA) = 0x00; 465 while ((via_reg(VIA2, 0x200) == 0x7f) && (delay >= 0)) 466 delay--; 467 468 if (delay < 0) { /* timeout */ 469 via_reg(VIA2, vDirA) = 0x00; 470 /* restore formar value */ 471 via_reg(VIA1, vIER) = via1_vIER; 472 return 0xffffcd38; 473 } 474 } 475 } /* end switch */ 476 477 s = splhigh(); 478 479 via1_vDirA = via_reg(VIA1, vDirA); 480 via_reg(VIA1, vDirA) &= 0x7f; 481 482 pm_cmd = (u_char)(pmdata->command & 0xff); 483 if ((rval = pm_send_pm1(pm_cmd, ADBDelay * 8)) == 0) 484 break; /* send command succeeded */ 485 486 via_reg(VIA1, vDirA) = via1_vDirA; 487 splx(s); 488 } /* end for */ 489 490 /* failed to send a command */ 491 if (i == 7) { 492 via_reg(VIA2, vDirA) = 0x00; 493 /* restore formar value */ 494 via_reg(VIA1, vDirA) = via1_vDirA; 495 via_reg(VIA1, vIER) = via1_vIER; 496 return 0xffffcd38; 497 } 498 499 /* send # of PM data */ 500 num_pm_data = pmdata->num_data; 501 if ((rval = pm_send_pm1((u_char)(num_pm_data & 0xff), ADBDelay * 8)) != 0) 502 break; /* timeout */ 503 504 /* send PM data */ 505 pm_buf = (u_char *)pmdata->s_buf; 506 for (i = 0; i < num_pm_data; i++) 507 if ((rval = pm_send_pm1(pm_buf[i], ADBDelay * 8)) != 0) 508 break; /* timeout */ 509 if ((i != num_pm_data) && (num_pm_data != 0)) 510 break; /* timeout */ 511 512 /* Will PM IC return data? */ 513 if ((pm_cmd & 0x08) == 0) { 514 rval = 0; 515 break; /* no returned data */ 516 } 517 518 rval = 0xffffcd37; 519 if (pm_wait_busy(ADBDelay) != 0) 520 break; /* timeout */ 521 522 /* receive PM command */ 523 if ((rval = pm_receive_pm1(&pm_data)) != 0) 524 break; 525 526 pmdata->command = pm_data; 527 528 /* receive number of PM data */ 529 if ((rval = pm_receive_pm1(&pm_data)) != 0) 530 break; /* timeout */ 531 num_pm_data = pm_data; 532 pmdata->num_data = num_pm_data; 533 534 /* receive PM data */ 535 pm_buf = (u_char *)pmdata->r_buf; 536 for (i = 0; i < num_pm_data; i++) { 537 if ((rval = pm_receive_pm1(&pm_data)) != 0) 538 break; /* timeout */ 539 pm_buf[i] = pm_data; 540 } 541 542 rval = 0; 543 } 544 545 via_reg(VIA2, vDirA) = 0x00; 546 547 /* restore formar value */ 548 via_reg(VIA1, vDirA) = via1_vDirA; 549 via_reg(VIA1, vIER) = via1_vIER; 550 if (s != 0x81815963) 551 splx(s); 552 553 return rval; 554} 555 556 557/* 558 * My PM interrupt routine for PB1XX series 559 */ 560void 561pm_intr_pm1() 562{ 563 int s; 564 int rval; 565 PMData pmdata; 566 567 s = splhigh(); 568 569 PM_VIA_CLR_INTR(); /* clear VIA1 interrupt */ 570 571 /* ask PM what happend */ 572 pmdata.command = 0x78; 573 pmdata.num_data = 0; 574 pmdata.data[0] = pmdata.data[1] = 0; 575 pmdata.s_buf = &pmdata.data[2]; 576 pmdata.r_buf = &pmdata.data[2]; 577 rval = pm_pmgrop_pm1(&pmdata); 578 if (rval != 0) { 579#ifdef ADB_DEBUG 580 if (adb_debug) 581 printf("pm: PM is not ready. error code=%08x\n", rval); 582#endif 583 splx(s); 584 } 585 586 if ((pmdata.data[2] & 0x10) == 0x10) { 587 if ((pmdata.data[2] & 0x0f) == 0) { 588 /* ADB data that were requested by TALK command */ 589 pm_adb_get_TALK_result(&pmdata); 590 } else if ((pmdata.data[2] & 0x08) == 0x8) { 591 /* PM is requesting to poll */ 592 pm_adb_poll_next_device_pm1(&pmdata); 593 } else if ((pmdata.data[2] & 0x04) == 0x4) { 594 /* ADB device event */ 595 pm_adb_get_ADB_data(&pmdata); 596 } 597 } else { 598#ifdef ADB_DEBUG 599 if (adb_debug) 600 pm_printerr("driver does not supported this event.", 601 rval, pmdata.num_data, pmdata.data); 602#endif 603 } 604 605 splx(s); 606} 607 608 609 610/* 611 * Functions for the PB Duo series and the PB 5XX series 612 */ 613 614/* 615 * Receive data from PM for the PB Duo series and the PB 5XX series 616 */ 617int 618pm_receive_pm2(data) 619 u_char *data; 620{ 621 int i; 622 int rval; 623 624 rval = 0xffffcd34; 625 626 switch (1) { 627 default: 628 /* set VIA SR to input mode */ 629 via_reg(VIA1, vACR) |= 0x0c; 630 via_reg(VIA1, vACR) &= ~0x10; 631 i = PM_SR(); 632 633 PM_SET_STATE_ACKOFF(); 634 if (pm_wait_busy((int)ADBDelay*32) != 0) 635 break; /* timeout */ 636 637 PM_SET_STATE_ACKON(); 638 rval = 0xffffcd33; 639 if (pm_wait_free((int)ADBDelay*32) == 0) 640 break; /* timeout */ 641 642 *data = PM_SR(); 643 rval = 0; 644 645 break; 646 } 647 648 PM_SET_STATE_ACKON(); 649 via_reg(VIA1, vACR) |= 0x1c; 650 651 return rval; 652} 653 654 655 656/* 657 * Send data to PM for the PB Duo series and the PB 5XX series 658 */ 659int 660pm_send_pm2(data) 661 u_char data; 662{ 663 int rval; 664 665 via_reg(VIA1, vACR) |= 0x1c; 666 PM_SR() = data; 667 668 PM_SET_STATE_ACKOFF(); 669 rval = 0xffffcd36; 670 if (pm_wait_busy((int)ADBDelay*32) != 0) { 671 PM_SET_STATE_ACKON(); 672 673 via_reg(VIA1, vACR) |= 0x1c; 674 675 return rval; 676 } 677 678 PM_SET_STATE_ACKON(); 679 rval = 0xffffcd35; 680 if (pm_wait_free((int)ADBDelay*32) != 0) 681 rval = 0; 682 683 PM_SET_STATE_ACKON(); 684 via_reg(VIA1, vACR) |= 0x1c; 685 686 return rval; 687} 688 689 690 691/* 692 * My PMgrOp routine for the PB Duo series and the PB 5XX series 693 */ 694int 695pm_pmgrop_pm2(pmdata) 696 PMData *pmdata; 697{ 698 int i; 699 int s; 700 u_char via1_vIER; 701 int rval = 0; 702 int num_pm_data = 0; 703 u_char pm_cmd; 704 short pm_num_rx_data; 705 u_char pm_data; 706 u_char *pm_buf; 707 708 s = splhigh(); 709 710 /* disable all inetrrupts but PM */ 711 via1_vIER = 0x10; 712 via1_vIER &= via_reg(VIA1, vIER); 713 via_reg(VIA1, vIER) = via1_vIER; 714 if (via1_vIER != 0x0) 715 via1_vIER |= 0x80; 716 717 switch (pmdata->command) { 718 default: 719 /* wait until PM is free */ 720 pm_cmd = (u_char)(pmdata->command & 0xff); 721 rval = 0xcd38; 722 if (pm_wait_free(ADBDelay * 4) == 0) 723 break; /* timeout */ 724 725 if (HwCfgFlags3 & 0x00200000) { 726 /* PB 160, PB 165(c), PB 180(c)? */ 727 int delay = ADBDelay * 16; 728 729 via_reg(VIA2, vDirA) = 0x00; 730 while ((via_reg(VIA2, 0x200) == 0x07) && 731 (delay >= 0)) 732 delay--; 733 734 if (delay < 0) { 735 rval = 0xffffcd38; 736 break; /* timeout */ 737 } 738 } 739 740 /* send PM command */ 741 if ((rval = pm_send_pm2((u_char)(pm_cmd & 0xff)))) 742 break; /* timeout */ 743 744 /* send number of PM data */ 745 num_pm_data = pmdata->num_data; 746 if (HwCfgFlags3 & 0x00020000) { /* PB Duo, PB 5XX */ 747 if (pm_send_cmd_type[pm_cmd] < 0) { 748 if ((rval = pm_send_pm2((u_char)(num_pm_data & 0xff))) != 0) 749 break; /* timeout */ 750 pmdata->command = 0; 751 } 752 } else { /* PB 1XX series ? */ 753 if ((rval = pm_send_pm2((u_char)(num_pm_data & 0xff))) != 0) 754 break; /* timeout */ 755 } 756 /* send PM data */ 757 pm_buf = (u_char *)pmdata->s_buf; 758 for (i = 0 ; i < num_pm_data; i++) 759 if ((rval = pm_send_pm2(pm_buf[i])) != 0) 760 break; /* timeout */ 761 if (i != num_pm_data) 762 break; /* timeout */ 763 764 765 /* check if PM will send me data */ 766 pm_num_rx_data = pm_receive_cmd_type[pm_cmd]; 767 pmdata->num_data = pm_num_rx_data; 768 if (pm_num_rx_data == 0) { 769 rval = 0; 770 break; /* no return data */ 771 } 772 773 /* receive PM command */ 774 pm_data = pmdata->command; 775 if (HwCfgFlags3 & 0x00020000) { /* PB Duo, PB 5XX */ 776 pm_num_rx_data--; 777 if (pm_num_rx_data == 0) 778 if ((rval = pm_receive_pm2(&pm_data)) != 0) { 779 rval = 0xffffcd37; 780 break; 781 } 782 pmdata->command = pm_data; 783 } else { /* PB 1XX series ? */ 784 if ((rval = pm_receive_pm2(&pm_data)) != 0) { 785 rval = 0xffffcd37; 786 break; 787 } 788 pmdata->command = pm_data; 789 } 790 791 /* receive number of PM data */ 792 if (HwCfgFlags3 & 0x00020000) { /* PB Duo, PB 5XX */ 793 if (pm_num_rx_data < 0) { 794 if ((rval = pm_receive_pm2(&pm_data)) != 0) 795 break; /* timeout */ 796 num_pm_data = pm_data; 797 } else 798 num_pm_data = pm_num_rx_data; 799 pmdata->num_data = num_pm_data; 800 } else { /* PB 1XX serias ? */ 801 if ((rval = pm_receive_pm2(&pm_data)) != 0) 802 break; /* timeout */ 803 num_pm_data = pm_data; 804 pmdata->num_data = num_pm_data; 805 } 806 807 /* receive PM data */ 808 pm_buf = (u_char *)pmdata->r_buf; 809 for (i = 0; i < num_pm_data; i++) { 810 if ((rval = pm_receive_pm2(&pm_data)) != 0) 811 break; /* timeout */ 812 pm_buf[i] = pm_data; 813 } 814 815 rval = 0; 816 } 817 818 /* restore former value */ 819 via_reg(VIA1, vIER) = via1_vIER; 820 splx(s); 821 822 return rval; 823} 824 825 826/* 827 * My PM interrupt routine for the PB Duo series and the PB 5XX series 828 */ 829void 830pm_intr_pm2() 831{ 832 int s; 833 int rval; 834 PMData pmdata; 835 836 s = splhigh(); 837 838 PM_VIA_CLR_INTR(); /* clear VIA1 interrupt */ 839 /* ask PM what happend */ 840 pmdata.command = 0x78; 841 pmdata.num_data = 0; 842 pmdata.s_buf = &pmdata.data[2]; 843 pmdata.r_buf = &pmdata.data[2]; 844 rval = pm_pmgrop_pm2(&pmdata); 845 if (rval != 0) { 846#ifdef ADB_DEBUG 847 if (adb_debug) 848 printf("pm: PM is not ready. error code: %08x\n", rval); 849#endif 850 splx(s); 851 } 852 853 switch ((u_int)(pmdata.data[2] & 0xff)) { 854 case 0x00: /* 1 sec interrupt? */ 855 break; 856 case 0x80: /* 1 sec interrupt? */ 857 pm_counter++; 858 break; 859 case 0x08: /* Brightness/Contrast button on LCD panel */ 860 /* get brightness and contrast of the LCD */ 861 pm_LCD_brightness = (u_int)pmdata.data[3] & 0xff; 862 pm_LCD_contrast = (u_int)pmdata.data[4] & 0xff; 863/* 864 pm_printerr("#08", rval, pmdata.num_data, pmdata.data); 865 pmdata.command = 0x33; 866 pmdata.num_data = 1; 867 pmdata.s_buf = pmdata.data; 868 pmdata.r_buf = pmdata.data; 869 pmdata.data[0] = pm_LCD_contrast; 870 rval = pm_pmgrop_pm2(&pmdata); 871 pm_printerr("#33", rval, pmdata.num_data, pmdata.data); 872*/ 873 /* this is an experimental code */ 874 pmdata.command = 0x41; 875 pmdata.num_data = 1; 876 pmdata.s_buf = pmdata.data; 877 pmdata.r_buf = pmdata.data; 878 pm_LCD_brightness = 0x7f - pm_LCD_brightness / 2; 879 if (pm_LCD_brightness < 0x25) 880 pm_LCD_brightness = 0x25; 881 if (pm_LCD_brightness > 0x5a) 882 pm_LCD_brightness = 0x7f; 883 pmdata.data[0] = pm_LCD_brightness; 884 rval = pm_pmgrop_pm2(&pmdata); 885 break; 886 case 0x10: /* ADB data that were requested by TALK command */ 887 case 0x14: 888 pm_adb_get_TALK_result(&pmdata); 889 break; 890 case 0x16: /* ADB device event */ 891 case 0x18: 892 case 0x1e: 893 pm_adb_get_ADB_data(&pmdata); 894 break; 895 default: 896#ifdef ADB_DEBUG 897 if (adb_debug) 898 pm_printerr("driver does not supported this event.", 899 pmdata.data[2], pmdata.num_data, 900 pmdata.data); 901#endif 902 break; 903 } 904 905 splx(s); 906} 907 908 909/* 910 * MRG-based PMgrOp routine 911 */ 912int 913pm_pmgrop_mrg(pmdata) 914 PMData *pmdata; 915{ 916 u_int32_t rval=0; 917 918 asm(" 919 movl %1, a0 920 .word 0xa085 921 movl d0, %0" 922 : "=g" (rval) 923 : "g" (pmdata) 924 : "a0", "d0" ); 925 926 return rval; 927} 928 929 930/* 931 * My PMgrOp routine 932 */ 933int 934pmgrop(pmdata) 935 PMData *pmdata; 936{ 937 switch (pmHardware) { 938 case PM_HW_PB1XX: 939 return (pm_pmgrop_pm1(pmdata)); 940 break; 941 case PM_HW_PB5XX: 942 return (pm_pmgrop_pm2(pmdata)); 943 break; 944 default: 945 /* return (pmgrop_mrg(pmdata)); */ 946 return 1; 947 } 948} 949 950 951/* 952 * My PM interrupt routine 953 */ 954void 955pm_intr() 956{ 957 switch (pmHardware) { 958 case PM_HW_PB1XX: 959 pm_intr_pm1(); 960 break; 961 case PM_HW_PB5XX: 962 pm_intr_pm2(); 963 break; 964 default: 965 break; 966 } 967} 968 969 970 971/* 972 * Synchronous ADBOp routine for the Power Manager 973 */ 974int 975pm_adb_op(buffer, compRout, data, command) 976 u_char *buffer; 977 void *compRout; 978 void *data; 979 int command; 980{ 981 int i; 982 int s; 983 int rval; 984 int delay; 985 PMData pmdata; 986 struct adbCommand packet; 987 988 if (adbWaiting == 1) 989 return 1; 990 991 s = splhigh(); 992 via_reg(VIA1, vIER) = 0x10; 993 994 adbBuffer = buffer; 995 adbCompRout = compRout; 996 adbCompData = data; 997 998 pmdata.command = 0x20; 999 pmdata.s_buf = pmdata.data; 1000 pmdata.r_buf = pmdata.data; 1001 1002 if ((command & 0xc) == 0x8) { /* if the command is LISTEN, add number of ADB data to number of PM data */ 1003 if (buffer != (u_char *)0) 1004 pmdata.num_data = buffer[0] + 3; 1005 } else { 1006 pmdata.num_data = 3; 1007 } 1008 1009 pmdata.data[0] = (u_char)(command & 0xff); 1010 pmdata.data[1] = 0; 1011 if ((command & 0xc) == 0x8) { /* if the command is LISTEN, copy ADB data to PM buffer */ 1012 if ((buffer != (u_char *)0) && (buffer[0] <= 24)) { 1013 pmdata.data[2] = buffer[0]; /* number of data */ 1014 for (i = 0; i < buffer[0]; i++) 1015 pmdata.data[3 + i] = buffer[1 + i]; 1016 } else 1017 pmdata.data[2] = 0; 1018 } else 1019 pmdata.data[2] = 0; 1020 1021 if ((command & 0xc) != 0xc) { /* if the command is not TALK */ 1022 /* set up stuff for adb_pass_up */ 1023 packet.data[0] = 1 + pmdata.data[2]; 1024 packet.data[1] = command; 1025 for (i = 0; i < pmdata.data[2]; i++) 1026 packet.data[i+2] = pmdata.data[i+3]; 1027 packet.saveBuf = adbBuffer; 1028 packet.compRout = adbCompRout; 1029 packet.compData = adbCompData; 1030 packet.cmd = command; 1031 packet.unsol = 0; 1032 packet.ack_only = 1; 1033 ite_polling = 1; 1034 adb_pass_up(&packet); 1035 ite_polling = 0; 1036 } 1037 1038 rval = pmgrop(&pmdata); 1039 if (rval != 0) 1040 return 1; 1041 1042 adbWaiting = 1; 1043 adbWaitingCmd = command; 1044 1045 PM_VIA_INTR_ENABLE(); 1046 1047 /* wait until the PM interrupt is occured */ 1048 delay = 0x80000; 1049 while (adbWaiting == 1) { 1050 if ((via_reg(VIA1, vIFR) & 0x10) == 0x10) 1051 pm_intr(); 1052#ifdef PM_GRAB_SI 1053#if 0 1054 zshard(0); /* grab any serial interrupts */ 1055#else 1056 (void)intr_dispatch(0x70); 1057#endif 1058#endif 1059 if ((--delay) < 0) 1060 return 1; 1061 } 1062 1063 /* this command enables the interrupt by operating ADB devices */ 1064 if (HwCfgFlags3 & 0x00020000) { /* PB Duo series, PB 5XX series */ 1065 pmdata.command = 0x20; 1066 pmdata.num_data = 4; 1067 pmdata.s_buf = pmdata.data; 1068 pmdata.r_buf = pmdata.data; 1069 pmdata.data[0] = 0x00; 1070 pmdata.data[1] = 0x86; /* magic spell for awaking the PM */ 1071 pmdata.data[2] = 0x00; 1072 pmdata.data[3] = 0x0c; /* each bit may express the existent ADB device */ 1073 } else { /* PB 1XX series */ 1074 pmdata.command = 0x20; 1075 pmdata.num_data = 3; 1076 pmdata.s_buf = pmdata.data; 1077 pmdata.r_buf = pmdata.data; 1078 pmdata.data[0] = (u_char)(command & 0xf0) | 0xc; 1079 pmdata.data[1] = 0x04; 1080 pmdata.data[2] = 0x00; 1081 } 1082 rval = pmgrop(&pmdata); 1083 1084 splx(s); 1085 return rval; 1086} 1087 1088 1089void 1090pm_adb_get_TALK_result(pmdata) 1091 PMData *pmdata; 1092{ 1093 int i; 1094 struct adbCommand packet; 1095 1096 /* set up data for adb_pass_up */ 1097 packet.data[0] = pmdata->num_data-1; 1098 packet.data[1] = pmdata->data[3]; 1099 for (i = 0; i <packet.data[0]-1; i++) 1100 packet.data[i+2] = pmdata->data[i+4]; 1101 1102 packet.saveBuf = adbBuffer; 1103 packet.compRout = adbCompRout; 1104 packet.compData = adbCompData; 1105 packet.unsol = 0; 1106 packet.ack_only = 0; 1107 ite_polling = 1; 1108 adb_pass_up(&packet); 1109 ite_polling = 0; 1110 1111 adbWaiting = 0; 1112 adbBuffer = (long)0; 1113 adbCompRout = (long)0; 1114 adbCompData = (long)0; 1115} 1116 1117 1118void 1119pm_adb_get_ADB_data(pmdata) 1120 PMData *pmdata; 1121{ 1122 int i; 1123 struct adbCommand packet; 1124 1125 /* set up data for adb_pass_up */ 1126 packet.data[0] = pmdata->num_data-1; /* number of raw data */ 1127 packet.data[1] = pmdata->data[3]; /* ADB command */ 1128 for (i = 0; i <packet.data[0]-1; i++) 1129 packet.data[i+2] = pmdata->data[i+4]; 1130 packet.unsol = 1; 1131 packet.ack_only = 0; 1132 adb_pass_up(&packet); 1133} 1134 1135 1136void 1137pm_adb_poll_next_device_pm1(pmdata) 1138 PMData *pmdata; 1139{ 1140 int i; 1141 int ndid; 1142 u_short bendid = 0x1; 1143 int rval; 1144 PMData tmp_pmdata; 1145 1146 /* find another existent ADB device to poll */ 1147 for (i = 1; i < 16; i++) { 1148 ndid = (((pmdata->data[3] & 0xf0) >> 4) + i) & 0xf; 1149 bendid <<= ndid; 1150 if ((pm_existent_ADB_devices & bendid) != 0) 1151 break; 1152 } 1153 1154 /* poll the other device */ 1155 tmp_pmdata.command = 0x20; 1156 tmp_pmdata.num_data = 3; 1157 tmp_pmdata.s_buf = tmp_pmdata.data; 1158 tmp_pmdata.r_buf = tmp_pmdata.data; 1159 tmp_pmdata.data[0] = (u_char)(ndid << 4) | 0xc; 1160 tmp_pmdata.data[1] = 0x04; /* magic spell for awaking the PM */ 1161 tmp_pmdata.data[2] = 0x00; 1162 rval = pmgrop(&tmp_pmdata); 1163} 1164 1165 1166 1167