; ;================================================================================================== ; FLASH DRIVER FOR FLASH & EEPROM PROGRAMMING ; ; 26 SEP 2020 - CHIP IDENTIFICATION IMPLMENTED -- PHIL SUMMERS ; - CHIP ERASE IMPLEMENTED ;================================================================================================== ; ; UPPER RAM BANK IS ALWAYS AVAILABLE REGARDLESS OF MEMORY BANK SELECTION. HBX_BNKSEL AND ; HB_CURBNK ARE ALWAYS AVAILABLE IN UPPER MEMORY AND THE STACK IS ALSO IN UPPER MEMORY DURING ; BIOS INITIALIZATION. TO ACCESS THE FLASH CHIP FEATURES, CODE IS COPIED TO THE UPPER RAM BANK ; AND THE FLASH CHIP IS SWITCHED INTO THE LOWER BANK. ; ; INSPIRED BY WILL SOWERBUTTS FLASH4 UTILITY - https://github.com/willsowerbutts/flash4/ ; FF_INIT: CALL NEWLINE ; FORMATTING PRTS("FF: FLASH ID:$") ; LD (FF_STACK),SP ; SAVE STACK LD HL,(FF_STACK) LD BC,FF_I_SZ ; CODE SIZE REQUIRED CCF ; CREATE A RELOCATABLE SBC HL,BC ; CODE BUFFER IN THE LD SP,HL ; STACK AREA ; PUSH HL ; SAVE THE EXECUTE ADDRESS EX DE,HL ; PUT EXECUTE / START ADDRESS IN DE LD HL,FF_IDENT ; COPY OUR RELOCATABLE LDIR ; CODE TO THE BUFFER ; LD A,(HB_CURBNK) ; WE ARE STARTING IN HB_CURBNK LD B,A ; WHICH IS THE RAM COPY OF THE BIOS LD A,BID_BOOT ; BID_BOOT IS ROM BANK 0 ; POP HL ; CALL OUR RELOCATABLE CODE CALL JPHL ; LD HL,(FF_STACK) ; RESTORE ORIGINAL LD SP,HL ; STACK POSITION ; LD H,E LD L,D CALL PRTHEXWORDHL ; DISPLAY FLASH ID CALL PC_SPACE ; LD HL,FF_TABLE ; SEARCH THROUGH THE FLASH LD BC,FF_T_CNT ; TABLE TO FIND A MATCH FF_NXT1:LD A,(HL) CP D JR NZ,FF_NXT0 ; FIRST BYTE DOES NOT MATCH ; INC HL LD A,(HL) CP E DEC HL JR NZ,FF_NXT0 ; SECOND BYTE DOES NOT MATCH ; INC HL INC HL JR FF_NXT2 ; MATCH SO EXIT ; FF_NXT0:PUSH BC ; WE DIDN'T MATCH SO POINT LD BC,17 ; TO THE NEXT TABLE ENTRY ADD HL,BC POP BC ; LD A,B ; CHECK IF WE REACHED THE OR C ; END OF THE TABLE DEC BC JR NZ,FF_NXT1 ; NOT AT END YET ; LD HL,FF_UNKNOWN ; WE REACHED THE END WITHOUT A MATCH ; FF_NXT2:CALL PRTSTR ; AFTER SEARCH DISPLAY THE RESULT ; CALL FF_EINIT ; ERASE TEST XOR A ; INIT SUCCEEDED RET ; ;====================================================================== ; IDENTIFY FLASH CHIP. THIS CODE IS RELOCATED AND EXECUTED IN THE STACK. ; IT SWITCHES THE BOTTOM BANK TO ROM BANK 0 I.E. BOTTOM OF CHIP ADDRESS RANGE. ; RETURNS WITH CHIP ID IN DE AND RETURNS THE BOTTOM BANK TO INITIAL STATE. ;====================================================================== ; FF_IDENT: ; FLASH ROM ID CODE `` HB_DI CALL HBX_BNKSEL ; SELECT ROM BANK 0 ; LD A,$AA ; SET IDENTIFY MODE LD ($5555),A ; LD A,$55 LD ($2AAA),A ; LD A,$90 LD ($5555),A ; LD DE,($0000) ; LD A,$F0 ; EXIT IDENTIFY MODE LD ($5555),A ; LD A,B ; RETURN TO ORIGINAL BANK CALL HBX_BNKSEL ; WHICH IS OUR RAM BIOS COPY HB_EI ; RET ; FF_I_SZ .EQU $-FF_IDENT ; ;====================================================================== ; ERASE FLASH CHIP. ;====================================================================== ; FF_EINIT: LD (FF_STACK),SP ; SAVE STACK LD HL,(FF_STACK) ; LD BC,FF_E_SZ ; CODE SIZE REQUIRED CCF ; CREATE A RELOCATABLE SBC HL,BC ; CODE BUFFER IN THE LD SP,HL ; STACK AREA ; PUSH HL ; SAVE THE EXECUTE ADDRESS EX DE,HL ; PUT EXECUTE / START ADDRESS IN DE LD HL,FF_ERASE ; COPY OUR RELOCATABLE LDIR ; CODE TO THE BUFFER ; LD A,(HB_CURBNK) ; WE ARE STARTING IN HB_CURBNK LD B,A ; WHICH IS THE RAM COPY OF THE BIOS LD A,BID_BOOT ; BID_BOOT IS ROM BANK 0 ; POP HL ; CALL OUR RELOCATABLE CODE CALL JPHL ; LD HL,(FF_STACK) ; RESTORE ORIGINAL LD SP,HL ; STACK POSITION ; LD A,C ; RETURN WITH STATUS IN A RET ; ;====================================================================== ; ERASE FLASH CHIP. THIS CODE IS RELOCATED AND EXECUTED IN THE STACK. ; IT SWITCHES THE BOTTOM BANK TO ROM BANK 0 I.E. BOTTOM OF CHIP ADDRESS RANGE. ; RETURNS THE BOTTOM BANK TO INITIAL STATE. ERASE COMMAND IS ISSUED TO ; THE FLASH CHIP AND THEN TOGGLE BIT IS MONITORED FOR COMPLETION. ; RETURN C=0 FOR SUCCESS OR C=FF FOR FAILURE. ;====================================================================== ; FF_ERASE: HB_DI CALL HBX_BNKSEL ; SELECT ROM BANK 0 ; LD A,$AA ; SET CHIP ERASE LD ($5555),A ; LD A,$55 LD ($2AAA),A ; LD A,$80 LD ($5555),A ; LD A,$AA LD ($5555),A ; LD A,$55 LD ($2AAA),A ; LD A,$10 LD ($5555),A ; LD HL,$5555 ; DO TWO SUCCESSIVE READS LD A,(HL) ; FROM THE SAME FLASH ADDRESS. FF_WT2: LD C,(HL) ; IF TOGGLE BIT (BIT 6) XOR C ; IS THE SAME ON BOTH READS BIT 6,A ; THEN ERASE IS COMPLETE SO EXIT. JR Z,FF_WT1 ; Z TRUE IF BIT 6=0 I.E. "NO TOGGLE" WAS DETECTED. ; LD A,C ; OPERATION IS NOT COMPLETE. CHECK TIMEOUT BIT (BIT 5). BIT 5,C ; IF NO TIMEOUT YET THEN LOOP BACK AND KEEP CHECKING TOGGLE STATUS JR Z,FF_WT2 ; IF BIT 5=0 THEN RETRY; NZ TRUE IF BIT 5=1 ; LD A,(HL) ; WE GOT A TIMOUT. RECHECK TOGGLE BIT IN CASE WE DID COMPLETE XOR (HL) ; THE OPERATION. DO TWO SUCCESSIVE READS. ARE THEY THE SAME? BIT 6,A ; IF THEY ARE THEN OPERATION WAS COMPLETED JR Z,FF_WT1 ; OTHERWISE ERASE OPERATION FAILED OR TIMED OUT. ; LD C,$FF ; SET FAIL STATUS JR FF_WT3 ; FF_WT1: LD C,0 ; SET SUCCESS STATUS FF_WT3: LD A,B ; RETURN TO ORIGINAL BANK CALL HBX_BNKSEL ; WHICH IS OUR RAM BIOS COPY HB_EI ; RET ; FF_E_SZ .EQU $-FF_ERASE ; ;====================================================================== ; ERASE FLASH SECTOR. ;====================================================================== ; ; FF_SINIT: LD (FF_STACK),SP ; SAVE STACK LD HL,(FF_STACK) ; LD BC,FF_S_SZ ; CODE SIZE REQUIRED CCF ; CREATE A RELOCATABLE SBC HL,BC ; CODE BUFFER IN THE LD SP,HL ; STACK AREA ; PUSH HL ; SAVE THE EXECUTE ADDRESS EX DE,HL ; PUT EXECUTE / START ADDRESS IN DE LD HL,FF_ERASE ; COPY OUR RELOCATABLE LDIR ; CODE TO THE BUFFER ; LD A,(HB_CURBNK) ; WE ARE STARTING IN HB_CURBNK LD B,A ; WHICH IS THE RAM COPY OF THE BIOS ; ; SELECT THE CORRECT ROM BANK ; LD A,BID_BOOT ; BID_BOOT IS ROM BANK 0 ; POP HL ; CALL OUR RELOCATABLE CODE CALL JPHL ; LD HL,(FF_STACK) ; RESTORE ORIGINAL LD SP,HL ; STACK POSITION ; XOR A RET ; ;====================================================================== ; ERASE FLASH CHIP SECTOR. THIS CODE IS RELOCATED AND EXECUTED IN THE STACK. ; IT SWITCHES THE REQUIRED BANK TO THE BOTTOM OF CHIP ADDRESS RANGE. ; RETURNS THE BOTTOM BANK TO INITIAL STATE. ERASE SECTOR COMMAND IS ISSUED TO ; THE FLASH CHIP AND THEN TOGGLE BIT IS MONITORED FOR COMPLETION. ; ON ENTRY HL CONTAINS THE SECTOR TO ERASE. ;====================================================================== ; FF_SERASE: HB_DI CALL HBX_BNKSEL ; SELECT ROM BANK 0 ; LD A,$AA ; SET CHIP ERASE LD ($5555),A ; LD A,$55 LD ($2AAA),A ; LD A,$80 LD ($5555),A ; LD A,$AA LD ($5555),A ; LD A,$55 LD ($2AAA),A ; LD A,$30 ; SECTOR ADDRESS LD (HL),A ; LD A,B ; RETURN TO ORIGINAL BANK CALL HBX_BNKSEL ; WHICH IS OUR RAM BIOS COPY HB_EI ; RET ; FF_S_SZ .EQU $-FF_SERASE ; ; FLASH STYLE ; ST_NORMAL .EQU 0 ST_ERASE_CHIP .EQU 1 ST_PROGRAM_SECT .EQU 2 ; ; FLASH CHIP MACRO ; #DEFINE FF_CHIP(FFROMID,FFROMNM,FFROMSS,FFROMMD) \ #DEFCONT ; \ #DEFCONT .DW FFROMID \ #DEFCONT .DB FFROMNM \ #DEFCONT .DW FFROMSS \ #DEFCONT .DW FFROMMD \ #DEFCONT ; ; ; FLASH CHIP LIST ; FF_TABLE: FF_CHIP(00120H,"29F010$ ",128,ST_NORMAL) FF_CHIP(001A4H,"29F040$ ",512,ST_NORMAL) FF_CHIP(01F04H,"AT49F001NT$",1024,ST_ERASE_CHIP) FF_CHIP(01F05H,"AT49F001N$ ",1024,ST_ERASE_CHIP) FF_CHIP(01F07H,"AT49F002N$ ",2048,ST_ERASE_CHIP) FF_CHIP(01F08H,"AT49F002NT$",2048,ST_ERASE_CHIP) FF_CHIP(01F13H,"AT49F040$ ",4096,ST_ERASE_CHIP) FF_CHIP(01F5DH,"AT29C512$ ",1,ST_PROGRAM_SECT) FF_CHIP(01FA4H,"AT29C040$ ",2,ST_PROGRAM_SECT) FF_CHIP(01FD5H,"AT29C010$ ",1,ST_PROGRAM_SECT) FF_CHIP(01FDAH,"AT29C020$ ",2,ST_PROGRAM_SECT) FF_CHIP(02020H,"M29F010$ ",128,ST_PROGRAM_SECT) FF_CHIP(020E2H,"M29F040$ ",512,ST_NORMAL) FF_CHIP(0BFB5H,"39F010$ ",32,ST_NORMAL) FF_CHIP(0BFB6H,"39F020$ ",32,ST_NORMAL) FF_CHIP(0BFB7H,"39F040$ ",32,ST_NORMAL) FF_CHIP(0C2A4H,"MX29F040$ ",512,ST_NORMAL) ; FF_T_CNT .EQU ($-FF_TABLE) / 17 FF_UNKNOWN .DB "UNKNOWN$" FF_STACK: .DW 0