this repo has no description
at main 442 lines 9.6 kB view raw
1/* 2 PMUEMDEV.c 3 4 Copyright (C) 2008 Paul C. Pratt 5 6 You can redistribute this file and/or modify it under the terms 7 of version 2 of the GNU General Public License as published by 8 the Free Software Foundation. You should have received a copy 9 of the license along with this file; see the file COPYING. 10 11 This file is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 license for more details. 15*/ 16 17/* 18 Power Management Unit EMulated DEVice 19*/ 20 21#include "PICOMMON.h" 22 23#if EmPMU 24 25#include "VIAEMDEV.h" 26 27#include "PMUEMDEV.h" 28 29/* 30 ReportAbnormalID unused 0x0E0E - 0x0EFF 31*/ 32 33enum { 34 kPMUStateReadyForCommand, 35 kPMUStateRecievingLength, 36 kPMUStateRecievingBuffer, 37 kPMUStateRecievedCommand, 38 kPMUStateSendLength, 39 kPMUStateSendBuffer, 40 41 kPMUStates 42}; 43 44#define PMU_BuffSz 8 45LOCALVAR ui3b PMU_BuffA[PMU_BuffSz]; 46LOCALVAR ui3p PMU_p; 47LOCALVAR ui3r PMU_rem; 48LOCALVAR ui3r PMU_i; 49 50LOCALVAR int PMUState = kPMUStateReadyForCommand; 51 52LOCALVAR ui3r PMU_CurCommand; 53LOCALVAR ui3r PMU_SendNext; 54LOCALVAR ui3r PMU_BuffL; 55 56LOCALPROC PmuStartSendResult(ui3r ResultCode, ui3r L) 57{ 58 PMU_SendNext = ResultCode; 59 PMU_BuffL = L; 60 PMUState = kPMUStateSendLength; 61} 62 63LOCALVAR ui3b PARAMRAM[128]; 64 65LOCALPROC PmuCheckCommandOp(void) 66{ 67 switch (PMU_CurCommand) { 68 case 0x10: /* kPMUpowerCntl - power plane/clock control */ 69 break; 70 case 0x32: /* kPMUxPramWrite - write extended PRAM byte(s) */ 71 if (kPMUStateRecievingBuffer == PMUState) { 72 if (0 == PMU_i) { 73 if (PMU_BuffL >= 2) { 74 PMU_p = PMU_BuffA; 75 PMU_rem = 2; 76 } else { 77 ReportAbnormalID(0x0E01, 78 "PMU_BuffL too small for kPMUxPramWrite"); 79 } 80 } else if (2 == PMU_i) { 81 if ((PMU_BuffA[1] + 2 == PMU_BuffL) 82 && (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80)) 83 { 84 PMU_p = &PARAMRAM[PMU_BuffA[0]]; 85 PMU_rem = PMU_BuffA[1]; 86 } else { 87 ReportAbnormalID(0x0E02, 88 "bad range for kPMUxPramWrite"); 89 } 90 } else { 91 ReportAbnormalID(0x0E03, 92 "Wrong PMU_i for kPMUpramWrite"); 93 } 94 } else if (kPMUStateRecievedCommand == PMUState) { 95 /* already done */ 96 } 97 break; 98#if 0 99 case 0xE2: /* kPMUdownloadStatus - PRAM status */ 100 break; 101#endif 102 case 0xE0: /* kPMUwritePmgrRAM - write to internal PMGR RAM */ 103 break; 104 case 0x21: /* kPMUpMgrADBoff - turn ADB auto-poll off */ 105 if (kPMUStateRecievedCommand == PMUState) { 106 if (0 != PMU_BuffL) { 107 ReportAbnormalID(0x0E04, 108 "kPMUpMgrADBoff nonzero length"); 109 } 110 } 111 break; 112 case 0xEC: /* kPMUPmgrSelfTest - run the PMGR selftest */ 113 if (kPMUStateRecievedCommand == PMUState) { 114 PmuStartSendResult(0, 0); 115 } 116 break; 117 case 0x78: 118 /* kPMUreadINT - get PMGR interrupt data */ 119 case 0x68: 120 /* 121 kPMUbatteryRead - read battery/charger level and status 122 */ 123 case 0x7F: 124 /* 125 kPMUsleepReq - put the system to sleep (sleepSig='MATT') 126 */ 127 if (kPMUStateRecievedCommand == PMUState) { 128 PMU_BuffA[0] = 0; 129 PmuStartSendResult(0, 1); 130 } 131 break; 132 case 0xE8: /* kPMUreadPmgrRAM - read from internal PMGR RAM */ 133 if (kPMUStateRecievedCommand == PMUState) { 134 if ((3 == PMU_BuffL) 135 && (0 == PMU_BuffA[0]) 136 && (0xEE == PMU_BuffA[1]) 137 && (1 == PMU_BuffA[2])) 138 { 139 PMU_BuffA[0] = 1 << 5; 140 PmuStartSendResult(0, 1); 141 } else { 142 PMU_BuffA[0] = 0; 143 PmuStartSendResult(0, 1); 144 /* ReportAbnormal("Unknown kPMUreadPmgrRAM op"); */ 145 } 146 } 147 break; 148 case 0x3A: /* kPMUxPramRead - read extended PRAM byte(s) */ 149 if (kPMUStateRecievedCommand == PMUState) { 150 if ((2 == PMU_BuffL) 151 && (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80)) 152 { 153 PMU_p = &PARAMRAM[PMU_BuffA[0]]; 154 PMU_rem = PMU_BuffA[1]; 155 PmuStartSendResult(0, PMU_rem); 156 } else { 157 ReportAbnormalID(0x0E05, 158 "Unknown kPMUxPramRead op"); 159 } 160 } 161 break; 162 case 0x38: 163 /* kPMUtimeRead - read the time from the clock chip */ 164 if (kPMUStateRecievedCommand == PMUState) { 165 if (0 == PMU_BuffL) { 166 PMU_BuffA[0] = 0; 167 PMU_BuffA[1] = 0; 168 PMU_BuffA[2] = 0; 169 PMU_BuffA[3] = 0; 170 PmuStartSendResult(0, 4); 171 } else { 172 ReportAbnormalID(0x0E06, "Unknown kPMUtimeRead op"); 173 } 174 } 175 break; 176 case 0x31: 177 /* 178 kPMUpramWrite - write the original 20 bytes of PRAM 179 (Portable only) 180 */ 181 if (kPMUStateRecievedCommand == PMUState) { 182 if (20 == PMU_BuffL) { 183 /* done */ 184 } else { 185 ReportAbnormalID(0x0E07, 186 "Unknown kPMUpramWrite op"); 187 } 188 } else if (kPMUStateRecievingBuffer == PMUState) { 189 if (20 == PMU_BuffL) { 190 if (0 == PMU_i) { 191 PMU_p = &PARAMRAM[16]; 192 PMU_rem = 16; 193 } else if (16 == PMU_i) { 194 PMU_p = &PARAMRAM[8]; 195 PMU_rem = 4; 196 } else { 197 ReportAbnormalID(0x0E08, 198 "Wrong PMU_i for kPMUpramWrite"); 199 } 200 } 201 } 202 break; 203 case 0x39: 204 /* 205 kPMUpramRead - read the original 20 bytes of PRAM 206 (Portable only) 207 */ 208 if (kPMUStateRecievedCommand == PMUState) { 209 if (0 == PMU_BuffL) { 210 PmuStartSendResult(0, 20); 211 } else { 212 ReportAbnormalID(0x0E09, "Unknown kPMUpramRead op"); 213 } 214 } else if (kPMUStateSendBuffer == PMUState) { 215#if 0 216 { 217 int i; 218 219 for (i = 0; i < PMU_BuffSz; ++i) { 220 PMU_BuffA[i] = 0; 221 } 222 } 223#endif 224 if (0 == PMU_i) { 225 PMU_p = &PARAMRAM[16]; 226 PMU_rem = 16; 227 } else if (16 == PMU_i) { 228 PMU_p = &PARAMRAM[8]; 229 PMU_rem = 4; 230 } else { 231 ReportAbnormalID(0x0E0A, 232 "Wrong PMU_i for kPMUpramRead"); 233 } 234 } 235 break; 236 default: 237 if (kPMUStateRecievedCommand == PMUState) { 238 ReportAbnormalID(0x0E0B, "Unknown PMU op"); 239#if dbglog_HAVE 240 dbglog_writeCStr("Unknown PMU op "); 241 dbglog_writeHex(PMU_CurCommand); 242 dbglog_writeReturn(); 243 dbglog_writeCStr("PMU_BuffL = "); 244 dbglog_writeHex(PMU_BuffL); 245 dbglog_writeReturn(); 246 if (PMU_BuffL <= PMU_BuffSz) { 247 int i; 248 249 for (i = 0; i < PMU_BuffL; ++i) { 250 dbglog_writeCStr("PMU_BuffA["); 251 dbglog_writeNum(i); 252 dbglog_writeCStr("] = "); 253 dbglog_writeHex(PMU_BuffA[i]); 254 dbglog_writeReturn(); 255 } 256 } 257#endif 258 } 259 break; 260 } 261} 262 263LOCALPROC LocBuffSetUpNextChunk(void) 264{ 265 PMU_p = PMU_BuffA; 266 PMU_rem = PMU_BuffL - PMU_i; 267 if (PMU_rem >= PMU_BuffSz) { 268 PMU_rem = PMU_BuffSz; 269 } 270} 271 272LOCALFUNC ui3r GetPMUbus(void) 273{ 274 ui3r v; 275 276 v = VIA1_iA7; 277 v <<= 1; 278 v |= VIA1_iA6; 279 v <<= 1; 280 v |= VIA1_iA5; 281 v <<= 1; 282 v |= VIA1_iA4; 283 v <<= 1; 284 v |= VIA1_iA3; 285 v <<= 1; 286 v |= VIA1_iA2; 287 v <<= 1; 288 v |= VIA1_iA1; 289 v <<= 1; 290 v |= VIA1_iA0; 291 292 return v; 293} 294 295LOCALPROC SetPMUbus(ui3r v) 296{ 297 VIA1_iA0 = v & 0x01; 298 v >>= 1; 299 VIA1_iA1 = v & 0x01; 300 v >>= 1; 301 VIA1_iA2 = v & 0x01; 302 v >>= 1; 303 VIA1_iA3 = v & 0x01; 304 v >>= 1; 305 VIA1_iA4 = v & 0x01; 306 v >>= 1; 307 VIA1_iA5 = v & 0x01; 308 v >>= 1; 309 VIA1_iA6 = v & 0x01; 310 v >>= 1; 311 VIA1_iA7 = v & 0x01; 312} 313 314LOCALVAR blnr PMU_Sending = falseblnr; 315 316LOCALPROC PmuCheckCommandCompletion(void) 317{ 318 if (PMU_i == PMU_BuffL) { 319 PMUState = kPMUStateRecievedCommand; 320 PmuCheckCommandOp(); 321 if ((PMU_CurCommand & 0x08) == 0) { 322 PMUState = kPMUStateReadyForCommand; 323 SetPMUbus(0xFF); 324 } else { 325 if (PMUState != kPMUStateSendLength) { 326 PmuStartSendResult(0xFF, 0); 327 PMUState = kPMUStateSendLength; 328 } 329 PMU_i = 0; 330 PMU_Sending = trueblnr; 331 ICT_add(kICT_PMU_Task, 332 20400UL * kCycleScale / 64 * kMyClockMult); 333 } 334 } 335} 336 337GLOBALPROC PmuToReady_ChangeNtfy(void) 338{ 339 if (PMU_Sending) { 340 PMU_Sending = falseblnr; 341 ReportAbnormalID(0x0E0C, 342 "PmuToReady_ChangeNtfy while PMU_Sending"); 343 PmuFromReady = 0; 344 } 345 switch (PMUState) { 346 case kPMUStateReadyForCommand: 347 if (! PmuToReady) { 348 PmuFromReady = 0; 349 } else { 350 PMU_CurCommand = GetPMUbus(); 351 PMUState = kPMUStateRecievingLength; 352 PmuFromReady = 1; 353 } 354 break; 355 case kPMUStateRecievingLength: 356 if (! PmuToReady) { 357 PmuFromReady = 0; 358 } else { 359 PMU_BuffL = GetPMUbus(); 360 PMU_i = 0; 361 PMU_rem = 0; 362 PMUState = kPMUStateRecievingBuffer; 363 PmuCheckCommandCompletion(); 364 PmuFromReady = 1; 365 } 366 break; 367 case kPMUStateRecievingBuffer: 368 if (! PmuToReady) { 369 PmuFromReady = 0; 370 } else { 371 ui3r v = GetPMUbus(); 372 if (0 == PMU_rem) { 373 PMU_p = nullpr; 374 PmuCheckCommandOp(); 375 if (nullpr == PMU_p) { 376 /* default handler */ 377 LocBuffSetUpNextChunk(); 378 } 379 } 380 if (nullpr == PMU_p) { 381 /* mini vmac bug if ever happens */ 382 ReportAbnormalID(0x0E0D, 383 "PMU_p null while kPMUStateRecievingBuffer"); 384 } 385 *PMU_p++ = v; 386 --PMU_rem; 387 ++PMU_i; 388 PmuCheckCommandCompletion(); 389 PmuFromReady = 1; 390 } 391 break; 392 case kPMUStateSendLength: 393 if (! PmuToReady) { 394 /* receiving */ 395 PmuFromReady = 1; 396 } else { 397 PMU_SendNext = PMU_BuffL; 398 PMUState = kPMUStateSendBuffer; 399 PMU_Sending = trueblnr; 400 ICT_add(kICT_PMU_Task, 401 20400UL * kCycleScale / 64 * kMyClockMult); 402 } 403 break; 404 case kPMUStateSendBuffer: 405 if (! PmuToReady) { 406 /* receiving */ 407 PmuFromReady = 1; 408 } else { 409 if (PMU_i == PMU_BuffL) { 410 PMUState = kPMUStateReadyForCommand; 411 SetPMUbus(0xFF); 412 } else { 413 if (0 == PMU_rem) { 414 PMU_p = nullpr; 415 PmuCheckCommandOp(); 416 if (nullpr == PMU_p) { 417 /* default handler */ 418 LocBuffSetUpNextChunk(); 419 } 420 } 421 PMU_SendNext = *PMU_p++; 422 --PMU_rem; 423 ++PMU_i; 424 PMU_Sending = trueblnr; 425 ICT_add(kICT_PMU_Task, 426 20400UL * kCycleScale / 64 * kMyClockMult); 427 } 428 } 429 break; 430 } 431} 432 433GLOBALPROC PMU_DoTask(void) 434{ 435 if (PMU_Sending) { 436 PMU_Sending = falseblnr; 437 SetPMUbus(PMU_SendNext); 438 PmuFromReady = 0; 439 } 440} 441 442#endif /* EmPMU */