1 /*---------------------------------------------------------------------------* 2 Project: TwlSDK - CARD - libraries 3 File: card_backup.c 4 5 Copyright 2007-2008 Nintendo. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Date:: 2009-01-13#$ 14 $Rev: 9813 $ 15 $Author: yosizaki $ 16 17 *---------------------------------------------------------------------------*/ 18 19 20 #include <nitro.h> 21 22 #include "../include/card_common.h" 23 #include "../include/card_spi.h" 24 25 26 #ifndef SDK_ARM9 27 SDK_ERROR("this code is only for ARM9"! 28 #endif // SDK_ARM9 29 30 31 /*---------------------------------------------------------------------------*/ 32 /* Constants */ 33 34 #include <nitro/version_begin.h> 35 SDK_DEFINE_MIDDLEWARE(cardi_backup_assert, "NINTENDO", "BACKUP"); 36 #include <nitro/version_end.h> 37 #define SDK_USING_BACKUP() SDK_USING_MIDDLEWARE(cardi_backup_assert) 38 39 40 /*---------------------------------------------------------------------------*/ 41 /* Variables */ 42 43 /* Cache of backup page last sent */ 44 static u8 CARDi_backup_cache_page_buf[256] ATTRIBUTE_ALIGN(32); 45 46 47 /*---------------------------------------------------------------------------*/ 48 /* Functions */ 49 50 /*---------------------------------------------------------------------------* 51 Name: CARDi_OnFifoRecv 52 53 Description: PXI FIFO word receive callback 54 55 Arguments: tag: PXI tag (always PXI_FIFO_TAG_FS) 56 data: Receive data 57 err: Error bit (according to old specs) 58 59 Returns: None. 60 *---------------------------------------------------------------------------*/ 61 void CARDi_OnFifoRecv(PXIFifoTag tag, u32 data, BOOL err) 62 { 63 #pragma unused(data) 64 if ((tag == PXI_FIFO_TAG_FS) && err) 65 { 66 CARDiCommon *const p = &cardi_common; 67 /* Receive reply from ARM7 and send a notification of completion */ 68 SDK_ASSERT(data == CARD_REQ_ACK); 69 p->flag &= ~CARD_STAT_WAITFOR7ACK; 70 OS_WakeupThreadDirect(p->current_thread_9); 71 } 72 } 73 74 /*---------------------------------------------------------------------------* 75 Name: CARDi_Request 76 77 Description: Sends request from ARM9 to ARM7 and blocks completion. 78 If the result is not CARD_RESULT_SUCCESS, retries the specified number of times. 79 (Locking of the specified bus and exclusive control of the task thread are guaranteed by the caller of this function.) 80 81 Sub-process repeatedly called in another command. 82 83 Arguments: req_type: Command request type 84 retry_max: Max. number of times to retry 85 86 Returns: If the result is CARD_RESULT_SUCCESS, TRUE. 87 *---------------------------------------------------------------------------*/ 88 static BOOL CARDi_Request(CARDiCommon *p, int req_type, int retry_count) 89 { 90 // Execute here if PXI not initialized 91 if ((p->flag & CARD_STAT_INIT_CMD) == 0) 92 { 93 p->flag |= CARD_STAT_INIT_CMD; 94 while (!PXI_IsCallbackReady(PXI_FIFO_TAG_FS, PXI_PROC_ARM7)) 95 { 96 OS_SpinWait(100); 97 } 98 // Send the first INIT command (recursive) 99 (void)CARDi_Request(p, CARD_REQ_INIT, 1); 100 } 101 // Flush the shared memory that has been set 102 DC_FlushRange(p->cmd, sizeof(*p->cmd)); 103 DC_WaitWriteBufferEmpty(); 104 105 // Register the thread pointer to receive a command response 106 p->current_thread_9 = OS_GetCurrentThread(); 107 108 do 109 { 110 // Send command request 111 p->flag |= CARD_STAT_WAITFOR7ACK; 112 CARDi_SendPxi((u32)req_type); 113 // If there are more arguments, perform additional sends 114 switch (req_type) 115 { 116 case CARD_REQ_INIT: 117 CARDi_SendPxi((u32)p->cmd); 118 break; 119 } 120 { 121 // Wait for the completion of the request from ARM7 122 OSIntrMode bak_psr = OS_DisableInterrupts(); 123 while ((p->flag & CARD_STAT_WAITFOR7ACK) != 0) 124 { 125 OS_SleepThread(NULL); 126 } 127 (void)OS_RestoreInterrupts(bak_psr); 128 } 129 DC_InvalidateRange(p->cmd, sizeof(*p->cmd)); 130 } 131 while ((p->cmd->result == CARD_RESULT_TIMEOUT) && (--retry_count > 0)); 132 133 return (p->cmd->result == CARD_RESULT_SUCCESS); 134 } 135 136 /*---------------------------------------------------------------------------* 137 Name: CARDi_RequestStreamCommandCore 138 139 Description: Core of command request processing that transfers data. 140 Called synchronously and asynchronously. 141 142 Arguments: p: Library's work buffer (passed by argument for efficiency) 143 144 Returns: None. 145 *---------------------------------------------------------------------------*/ 146 static void CARDi_RequestStreamCommandCore(CARDiCommon * p) 147 { 148 const int req_type = p->req_type; 149 const int req_mode = p->req_mode; 150 const int retry_count = p->req_retry; 151 u32 size = sizeof(CARDi_backup_cache_page_buf); 152 153 SDK_USING_BACKUP(); 154 155 /* Request at the page or sector level */ 156 if (req_type == CARD_REQ_ERASE_SECTOR_BACKUP) 157 { 158 size = CARD_GetBackupSectorSize(); 159 } 160 else if (req_type == CARD_REQ_ERASE_SUBSECTOR_BACKUP) 161 { 162 size = cardi_common.cmd->spec.subsect_size; 163 } 164 do 165 { 166 const u32 len = (size < p->len) ? size : p->len; 167 p->cmd->len = len; 168 169 /* Stops here if there has been a cancel request */ 170 if ((p->flag & CARD_STAT_CANCEL) != 0) 171 { 172 p->flag &= ~CARD_STAT_CANCEL; 173 p->cmd->result = CARD_RESULT_CANCELED; 174 break; 175 } 176 switch (req_mode) 177 { 178 case CARD_REQUEST_MODE_RECV: 179 /* Invalidate the buffer if command is receive-related */ 180 DC_InvalidateRange(CARDi_backup_cache_page_buf, len); 181 p->cmd->src = (u32)p->src; 182 p->cmd->dst = (u32)CARDi_backup_cache_page_buf; 183 break; 184 case CARD_REQUEST_MODE_SEND: 185 case CARD_REQUEST_MODE_SEND_VERIFY: 186 /* If command is send-related, copy the data to a temporary buffer */ 187 MI_CpuCopy8((const void *)p->src, CARDi_backup_cache_page_buf, len); 188 DC_FlushRange(CARDi_backup_cache_page_buf, len); 189 DC_WaitWriteBufferEmpty(); 190 p->cmd->src = (u32)CARDi_backup_cache_page_buf; 191 p->cmd->dst = (u32)p->dst; 192 break; 193 case CARD_REQUEST_MODE_SPECIAL: 194 /* Buffer operations are unnecessary */ 195 p->cmd->src = (u32)p->src; 196 p->cmd->dst = (u32)p->dst; 197 break; 198 } 199 /* Send a request */ 200 if (!CARDi_Request(p, req_type, retry_count)) 201 { 202 break; 203 } 204 /* If specified, make another verify request with the same settings. */ 205 if (req_mode == CARD_REQUEST_MODE_SEND_VERIFY) 206 { 207 if (!CARDi_Request(p, CARD_REQ_VERIFY_BACKUP, 1)) 208 { 209 break; 210 } 211 } 212 else if (req_mode == CARD_REQUEST_MODE_RECV) 213 { 214 /* Copy from cache */ 215 MI_CpuCopy8(CARDi_backup_cache_page_buf, (void *)p->dst, len); 216 } 217 p->src += len; 218 p->dst += len; 219 p->len -= len; 220 } 221 while (p->len > 0); 222 } 223 224 /*---------------------------------------------------------------------------* 225 Name: CARDi_RequestWriteSectorCommandCore 226 227 Description: Erases sectors and is the core process for program requests. 228 Called synchronously and asynchronously. 229 230 Arguments: p: Library's work buffer (passed by argument for efficiency) 231 232 Returns: None. 233 *---------------------------------------------------------------------------*/ 234 static void CARDi_RequestWriteSectorCommandCore(CARDiCommon * p) 235 { 236 const u32 sector_size = CARD_GetBackupSectorSize(); 237 SDK_USING_BACKUP(); 238 239 /* Return failure if the processing range is not an integer multiple of sector units */ 240 if ((((u32)p->dst | p->len) & (sector_size - 1)) != 0) 241 { 242 p->flag &= ~CARD_STAT_CANCEL; 243 p->cmd->result = CARD_RESULT_INVALID_PARAM; 244 } 245 else 246 { 247 /* Sector unit processing */ 248 for (; p->len > 0; p->len -= sector_size) 249 { 250 u32 len = sector_size; 251 /* Stops here if there has been a cancel request */ 252 if ((p->flag & CARD_STAT_CANCEL) != 0) 253 { 254 p->flag &= ~CARD_STAT_CANCEL; 255 p->cmd->result = CARD_RESULT_CANCELED; 256 break; 257 } 258 /* Sector deletion */ 259 p->cmd->dst = (u32)p->dst; 260 p->cmd->len = len; 261 if (!CARDi_Request(p, CARD_REQ_ERASE_SECTOR_BACKUP, 1)) 262 { 263 break; 264 } 265 while (len > 0) 266 { 267 const u32 page = sizeof(CARDi_backup_cache_page_buf); 268 /* Stops here if there has been a cancel request */ 269 if ((p->flag & CARD_STAT_CANCEL) != 0) 270 { 271 p->flag &= ~CARD_STAT_CANCEL; 272 p->cmd->result = CARD_RESULT_CANCELED; 273 break; 274 } 275 /* Program */ 276 MI_CpuCopy8((const void *)p->src, CARDi_backup_cache_page_buf, page); 277 DC_FlushRange(CARDi_backup_cache_page_buf, page); 278 DC_WaitWriteBufferEmpty(); 279 p->cmd->src = (u32)CARDi_backup_cache_page_buf; 280 p->cmd->dst = (u32)p->dst; 281 p->cmd->len = page; 282 if (!CARDi_Request(p, CARD_REQ_PROGRAM_BACKUP, CARD_RETRY_COUNT_MAX)) 283 { 284 break; 285 } 286 /* Verify if needed */ 287 if (p->req_mode == CARD_REQUEST_MODE_SEND_VERIFY) 288 { 289 if (!CARDi_Request(p, CARD_REQ_VERIFY_BACKUP, 1)) 290 { 291 break; 292 } 293 } 294 p->src += page; 295 p->dst += page; 296 len -= page; 297 } 298 } 299 } 300 } 301 302 /*---------------------------------------------------------------------------* 303 Name: CARDi_AccessStatusCore 304 305 Description: Core access processing for status register. 306 Called synchronously and asynchronously. 307 308 Arguments: p: Library's work buffer (passed by argument for efficiency) 309 310 Returns: None. 311 *---------------------------------------------------------------------------*/ 312 static void CARDi_AccessStatusCore(CARDiCommon *p) 313 { 314 CARDRequest command = (CARDRequest)CARDi_backup_cache_page_buf[1]; 315 DC_FlushRange(CARDi_backup_cache_page_buf, 1); 316 p->cmd->src = (u32)CARDi_backup_cache_page_buf; 317 p->cmd->dst = (u32)CARDi_backup_cache_page_buf; 318 (void)CARDi_Request(p, command, 1); 319 DC_InvalidateRange(CARDi_backup_cache_page_buf, 1); 320 } 321 322 /*---------------------------------------------------------------------------* 323 Name: CARDi_IdentifyBackupCore2 324 325 Description: Identifies the device type. 326 327 Arguments: type: Device type to be identified 328 329 Returns: None. 330 *---------------------------------------------------------------------------*/ 331 static void CARDi_IdentifyBackupCore2(CARDBackupType type) 332 { 333 /* 334 * Saves the obtained parameter in CARDiCommandArg. 335 * Ultimately this is completed by discarding the table. 336 */ 337 { 338 CARDiCommandArg *const p = cardi_common.cmd; 339 340 /* First, clear all parameters and set to NOT_USE state. */ 341 MI_CpuFill8(&p->spec, 0, sizeof(p->spec)); 342 p->type = type; 343 p->spec.caps = (CARD_BACKUP_CAPS_AVAILABLE | CARD_BACKUP_CAPS_READ_STATUS); 344 if (type != CARD_BACKUP_TYPE_NOT_USE) 345 { 346 /* 347 * Device type, total capacity and vendor can be obtained from 'type'. 348 * The vendor number is 0 unless the same type was adopted by several manufacturers and these types needed to be distinguished for some reason (for example, due to problems or bugs for some of them). 349 * 350 */ 351 const u32 size = (u32)(1 << ((type >> CARD_BACKUP_TYPE_SIZEBIT_SHIFT) & 352 CARD_BACKUP_TYPE_SIZEBIT_MASK)); 353 const int device = 354 ((type >> CARD_BACKUP_TYPE_DEVICE_SHIFT) & CARD_BACKUP_TYPE_DEVICE_MASK); 355 const int vender = 356 ((type >> CARD_BACKUP_TYPE_VENDER_SHIFT) & CARD_BACKUP_TYPE_VENDER_MASK); 357 358 p->spec.total_size = size; 359 /* Use 0xFF if the status register does not need to be corrected. (This is usually the case.) */ 360 p->spec.initial_status = 0xFF; 361 if (device == CARD_BACKUP_TYPE_DEVICE_EEPROM) 362 { 363 switch (size) 364 { 365 default: 366 goto invalid_type; 367 case 0x000200: // CARD_BACKUP_TYPE_EEPROM_4KBITS 368 p->spec.page_size = 0x10; 369 p->spec.addr_width = 1; 370 p->spec.program_page = 5; 371 p->spec.initial_status = 0xF0; 372 break; 373 case 0x002000: // CARD_BACKUP_TYPE_EEPROM_64KBITS 374 p->spec.page_size = 0x0020; 375 p->spec.addr_width = 2; 376 p->spec.program_page = 5; 377 p->spec.initial_status = 0x00; 378 break; 379 case 0x010000: // CARD_BACKUP_TYPE_EEPROM_512KBITS 380 p->spec.page_size = 0x0080; 381 p->spec.addr_width = 2; 382 p->spec.program_page = 10; 383 p->spec.initial_status = 0x00; 384 break; 385 case 0x020000: // CARD_BACKUP_TYPE_EEPROM_1MBITS 386 p->spec.page_size = 0x0100; 387 p->spec.addr_width = 3; 388 p->spec.program_page = 5; 389 p->spec.initial_status = 0x00; 390 break; 391 } 392 p->spec.sect_size = p->spec.page_size; 393 p->spec.caps |= CARD_BACKUP_CAPS_READ; 394 p->spec.caps |= CARD_BACKUP_CAPS_PROGRAM; 395 p->spec.caps |= CARD_BACKUP_CAPS_VERIFY; 396 p->spec.caps |= CARD_BACKUP_CAPS_WRITE_STATUS; 397 } 398 else if (device == CARD_BACKUP_TYPE_DEVICE_FLASH) 399 { 400 switch (size) 401 { 402 default: 403 goto invalid_type; 404 case 0x040000: // CARD_BACKUP_TYPE_FLASH_2MBITS 405 case 0x080000: // CARD_BACKUP_TYPE_FLASH_4MBITS 406 case 0x100000: // CARD_BACKUP_TYPE_FLASH_8MBITS 407 p->spec.write_page = 25; 408 p->spec.write_page_total = 300; 409 p->spec.erase_page = 300; 410 p->spec.erase_sector = 5000; 411 p->spec.caps |= CARD_BACKUP_CAPS_WRITE; 412 p->spec.caps |= CARD_BACKUP_CAPS_ERASE_PAGE; 413 break; 414 case 0x200000: // CARD_BACKUP_TYPE_FLASH_16MBITS 415 p->spec.write_page = 23; 416 p->spec.write_page_total = 300; 417 p->spec.erase_sector = 500; 418 p->spec.erase_sector_total = 5000; 419 p->spec.erase_chip = 10000; 420 p->spec.erase_chip_total = 60000; 421 p->spec.initial_status = 0x00; 422 p->spec.caps |= CARD_BACKUP_CAPS_WRITE; 423 p->spec.caps |= CARD_BACKUP_CAPS_ERASE_PAGE; 424 p->spec.caps |= CARD_BACKUP_CAPS_ERASE_CHIP; 425 p->spec.caps |= CARD_BACKUP_CAPS_WRITE_STATUS; 426 break; 427 case 0x400000: // CARD_BACKUP_TYPE_FLASH_32MBITS 428 p->spec.erase_sector = 600; 429 p->spec.erase_sector_total = 3000; 430 p->spec.erase_subsector = 70; 431 p->spec.erase_subsector_total = 150; 432 p->spec.erase_chip = 23000; 433 p->spec.erase_chip_total = 800000; 434 p->spec.initial_status = 0x00; 435 p->spec.subsect_size = 0x1000; 436 p->spec.caps |= CARD_BACKUP_CAPS_ERASE_SUBSECTOR; 437 p->spec.caps |= CARD_BACKUP_CAPS_ERASE_CHIP; 438 p->spec.caps |= CARD_BACKUP_CAPS_WRITE_STATUS; 439 break; 440 case 0x800000: 441 if (vender == 0) // CARD_BACKUP_TYPE_FLASH_64MBITS 442 { 443 p->spec.erase_sector = 1000; 444 p->spec.erase_sector_total = 3000; 445 p->spec.erase_chip = 68000; 446 p->spec.erase_chip_total = 160000; 447 p->spec.initial_status = 0x00; 448 p->spec.caps |= CARD_BACKUP_CAPS_ERASE_CHIP; 449 p->spec.caps |= CARD_BACKUP_CAPS_WRITE_STATUS; 450 } 451 else if (vender == 1) // CARD_BACKUP_TYPE_FLASH_64MBITS_EX 452 { 453 p->spec.erase_sector = 1000; 454 p->spec.erase_sector_total = 3000; 455 p->spec.erase_chip = 68000; 456 p->spec.erase_chip_total = 160000; 457 p->spec.initial_status = 0x84; 458 p->spec.caps |= CARD_BACKUP_CAPS_ERASE_CHIP; 459 p->spec.caps |= CARD_BACKUP_CAPS_WRITE_STATUS; 460 } 461 break; 462 } 463 p->spec.sect_size = 0x010000; 464 p->spec.page_size = 0x0100; 465 p->spec.addr_width = 3; 466 p->spec.program_page = 5; 467 p->spec.caps |= CARD_BACKUP_CAPS_READ; 468 p->spec.caps |= CARD_BACKUP_CAPS_PROGRAM; 469 p->spec.caps |= CARD_BACKUP_CAPS_VERIFY; 470 p->spec.caps |= CARD_BACKUP_CAPS_ERASE_SECTOR; 471 } 472 else if (device == CARD_BACKUP_TYPE_DEVICE_FRAM) 473 { 474 switch (size) 475 { 476 default: 477 goto invalid_type; 478 case 0x002000: // #CARD_BACKUP_TYPE_FRAM_64KBITS 479 case 0x008000: // #CARD_BACKUP_TYPE_FRAM_256KBITS 480 break; 481 } 482 p->spec.page_size = size; 483 p->spec.sect_size = size; 484 p->spec.addr_width = 2; 485 p->spec.initial_status = 0x00; 486 p->spec.caps |= CARD_BACKUP_CAPS_READ; 487 p->spec.caps |= CARD_BACKUP_CAPS_PROGRAM; 488 p->spec.caps |= CARD_BACKUP_CAPS_VERIFY; 489 p->spec.caps |= CARD_BACKUP_CAPS_WRITE_STATUS; 490 } 491 else 492 { 493 invalid_type: 494 p->type = CARD_BACKUP_TYPE_NOT_USE; 495 p->spec.total_size = 0; 496 cardi_common.cmd->result = CARD_RESULT_UNSUPPORTED; 497 return; 498 } 499 } 500 } 501 } 502 503 /*---------------------------------------------------------------------------* 504 Name: CARDi_IdentifyBackupCore 505 506 Description: Core process for identifying the device type. 507 Called synchronously and asynchronously. 508 509 Arguments: p: Library's work buffer (passed by argument for efficiency) 510 511 Returns: None. 512 *---------------------------------------------------------------------------*/ 513 static void CARDi_IdentifyBackupCore(CARDiCommon * p) 514 { 515 (void)CARDi_Request(p, CARD_REQ_IDENTIFY, 1); 516 /* 517 * Issue a read command for the first byte and get the result value. 518 * If there is a contact problem, damage, or lifespan problem, return TIMEOUT, regardless of the value. 519 * (TIMEOUT can be determined using a Read-Status command regardless of the device type) 520 */ 521 p->cmd->src = 0; 522 p->cmd->dst = (u32)CARDi_backup_cache_page_buf; 523 p->cmd->len = 1; 524 (void)CARDi_Request(p, CARD_REQ_READ_BACKUP, 1); 525 } 526 527 /*---------------------------------------------------------------------------* 528 Name: CARDi_BeginBackupCommand 529 530 Description: Starting process for backup operation command. 531 532 Arguments: callback: Completion callback (NULL if not used) 533 arg: Argument of completion callback (ignored if not used) 534 535 Returns: None. 536 *---------------------------------------------------------------------------*/ 537 static void CARDi_BeginBackupCommand(MIDmaCallback callback, void *arg) 538 { 539 SDK_USING_BACKUP(); 540 SDK_ASSERT(CARD_IsAvailable()); 541 SDK_ASSERTMSG(CARDi_GetTargetMode() == CARD_TARGET_BACKUP, 542 "[CARD] current locking target is not backup."); 543 CARD_CheckEnabled(); 544 if ((CARDi_GetAccessLevel() & CARD_ACCESS_LEVEL_BACKUP) == 0) 545 { 546 OS_TPanic("this program cannot access CARD-backup!"); 547 } 548 (void)CARDi_WaitForTask(&cardi_common, TRUE, callback, arg); 549 } 550 551 /*---------------------------------------------------------------------------* 552 Name: CARDi_RequestStreamCommand 553 554 Description: Issues request for command to transfer data. 555 556 Arguments: src: Transfer source offset or memory address 557 dst: Transfer destination offset or memory address 558 len: Transfer size 559 callback: Completion callback (NULL if not used) 560 arg: Argument of completion callback (ignored if not used) 561 is_async: If async operation was specified, TRUE 562 req_type: Command request type 563 req_retry: Maximum number of retries when command request fails 564 req_mode: Command request operation mode 565 566 Returns: TRUE if the process was successful. 567 *---------------------------------------------------------------------------*/ 568 BOOL CARDi_RequestStreamCommand(u32 src, u32 dst, u32 len, 569 MIDmaCallback callback, void *arg, BOOL is_async, 570 CARDRequest req_type, int req_retry, CARDRequestMode req_mode) 571 { 572 SDK_ASSERT(CARD_GetCurrentBackupType() != CARD_BACKUP_TYPE_NOT_USE); 573 574 CARDi_BeginBackupCommand(callback, arg); 575 576 { 577 CARDiCommon *p = &cardi_common; 578 p->src = src; 579 p->dst = dst; 580 p->len = len; 581 p->req_type = req_type; 582 p->req_retry = req_retry; 583 p->req_mode = req_mode; 584 } 585 586 return CARDi_ExecuteOldTypeTask(CARDi_RequestStreamCommandCore, is_async); 587 } 588 589 /*---------------------------------------------------------------------------* 590 Name: CARDi_AccessStatus 591 592 Description: Status read or write (for testing). 593 594 Arguments: command: CARD_REQ_READ_STATUS or CARD_REQ_WRITE_STATUS 595 value: The value to write, if CARD_REQ_WRITE_STATUS 596 597 Returns: Returns a value of 0 or higher if successful; a negative number otherwise. 598 *---------------------------------------------------------------------------*/ 599 int CARDi_AccessStatus(CARDRequest command, u8 value) 600 { 601 SDK_ASSERT(CARD_GetCurrentBackupType() != CARD_BACKUP_TYPE_NOT_USE); 602 603 CARDi_BeginBackupCommand(NULL, NULL); 604 605 // Use temporary buffer instead of the task argument 606 CARDi_backup_cache_page_buf[0] = value; 607 CARDi_backup_cache_page_buf[1] = (u8)command; 608 609 return CARDi_ExecuteOldTypeTask(CARDi_AccessStatusCore, FALSE) ? 610 CARDi_backup_cache_page_buf[0] : -1; 611 } 612 613 /*---------------------------------------------------------------------------* 614 Name: CARDi_RequestWriteSectorCommand 615 616 Description: Erases sectors and issues program requests. 617 618 Arguments: src: Transfer source memory address 619 dst: Transfer destination offset 620 len: Transfer size 621 verify: TRUE when performing a verify 622 callback: Completion callback (NULL if not used) 623 arg: Argument of completion callback (ignored if not used) 624 is_async: If async operation was specified, TRUE 625 626 Returns: TRUE if the process was successful. 627 *---------------------------------------------------------------------------*/ 628 BOOL CARDi_RequestWriteSectorCommand(u32 src, u32 dst, u32 len, BOOL verify, 629 MIDmaCallback callback, void *arg, BOOL is_async) 630 { 631 SDK_ASSERT(CARD_GetCurrentBackupType() != CARD_BACKUP_TYPE_NOT_USE); 632 633 CARDi_BeginBackupCommand(callback, arg); 634 635 { 636 CARDiCommon *p = &cardi_common; 637 p->src = src; 638 p->dst = dst; 639 p->len = len; 640 p->req_mode = verify ? CARD_REQUEST_MODE_SEND_VERIFY : CARD_REQUEST_MODE_SEND; 641 } 642 643 return CARDi_ExecuteOldTypeTask(CARDi_RequestWriteSectorCommandCore, is_async); 644 } 645 646 /*---------------------------------------------------------------------------* 647 Name: CARD_IdentifyBackup 648 649 Description: Specifies the card backup device type. 650 651 Arguments: type: Device classification of the CARDBackupType type 652 653 Returns: TRUE if the read test was successful. 654 *---------------------------------------------------------------------------*/ 655 BOOL CARD_IdentifyBackup(CARDBackupType type) 656 { 657 if (type == CARD_BACKUP_TYPE_NOT_USE) 658 { 659 OS_TPanic("cannot specify CARD_BACKUP_TYPE_NOT_USE."); 660 } 661 662 CARDi_BeginBackupCommand(NULL, NULL); 663 664 CARDi_IdentifyBackupCore2(type); 665 666 return CARDi_ExecuteOldTypeTask(CARDi_IdentifyBackupCore, FALSE); 667 } 668 669 /*---------------------------------------------------------------------------* 670 Name: CARD_GetCurrentBackupType 671 672 Description: Gets backup device type currently specified. 673 674 Arguments: None. 675 676 Returns: Backup device type currently specified. 677 *---------------------------------------------------------------------------*/ 678 CARDBackupType CARD_GetCurrentBackupType(void) 679 { 680 SDK_ASSERT(CARD_IsAvailable()); 681 682 return cardi_common.cmd->type; 683 } 684 685 /*---------------------------------------------------------------------------* 686 Name: CARD_GetBackupTotalSize 687 688 Description: Gets the overall size of the backup device currently specified. 689 690 Arguments: None. 691 692 Returns: Overall size of the backup device. 693 *---------------------------------------------------------------------------*/ 694 u32 CARD_GetBackupTotalSize(void) 695 { 696 SDK_ASSERT(CARD_IsAvailable()); 697 698 return cardi_common.cmd->spec.total_size; 699 } 700 701 /*---------------------------------------------------------------------------* 702 Name: CARD_GetBackupSectorSize 703 704 Description: Gets sector size of the backup device currently specified. 705 706 Arguments: None. 707 708 Returns: Sector size of the backup device. 709 *---------------------------------------------------------------------------*/ 710 u32 CARD_GetBackupSectorSize(void) 711 { 712 SDK_ASSERT(CARD_IsAvailable()); 713 714 return cardi_common.cmd->spec.sect_size; 715 } 716 717 /*---------------------------------------------------------------------------* 718 Name: CARD_GetBackupPageSize 719 720 Description: Gets page size of the backup device currently specified. 721 722 Arguments: None. 723 724 Returns: Page size of the backup device. 725 *---------------------------------------------------------------------------*/ 726 u32 CARD_GetBackupPageSize(void) 727 { 728 SDK_ASSERT(CARD_IsAvailable()); 729 730 return cardi_common.cmd->spec.page_size; 731 } 732 733 /*---------------------------------------------------------------------------* 734 Name: CARD_WaitBackupAsync 735 736 Description: Waits until the backup device access function is completed. 737 738 Arguments: None. 739 740 Returns: TRUE if the backup device access function that was called last is completed with CARD_RESULT_SUCCESS. FALSE, otherwise. 741 742 *---------------------------------------------------------------------------*/ 743 BOOL CARD_WaitBackupAsync(void) 744 { 745 return CARDi_WaitAsync(); 746 } 747 748 /*---------------------------------------------------------------------------* 749 Name: CARD_TryWaitBackupAsync 750 751 Description: Determines whether the backup device access function is completed. 752 753 Arguments: None. 754 755 Returns: TRUE if the backup device access function is completed. 756 *---------------------------------------------------------------------------*/ 757 BOOL CARD_TryWaitBackupAsync(void) 758 { 759 return CARDi_TryWaitAsync(); 760 } 761 762 /*---------------------------------------------------------------------------* 763 Name: CARD_CancelBackupAsync 764 765 Description: Requests termination to a backup device access function that is processing. 766 767 Arguments: None. 768 769 Returns: None. 770 *---------------------------------------------------------------------------*/ 771 void CARD_CancelBackupAsync(void) 772 { 773 OSIntrMode bak_cpsr = OS_DisableInterrupts(); 774 cardi_common.flag |= CARD_STAT_CANCEL; 775 (void)OS_RestoreInterrupts(bak_cpsr); 776 } 777