CON {{ *********************** CHANGELOG ************************** '' RR20180527 v141 proposed final SD & Monitor '' PBJ20180527 Added SD and FAT32 routines **************************************************************** }} '' ROM_Booter.spin2 v32i '' RR20190106 001a extract SD code only (for SD debugging) '' b sd-cs pullup failing '' c P2D2 works 24MHz (only Mixo 8GB HC U1) '' RR20190112 d '' RR20190215 f was failing due to 4K7 pulldown on P58 (SD DO pin), change to 33K pulldown '' g try clocks to release DO (requires minimum of 3 CLK pulses HL to release with CS=1) '' RR20190216 002a incorporate proposed fixes "Rom_Booter_v33_01a.spin" plus mods '' NEED TO FIND 2 LONGS '' bcd compile for P2-EVAL @25MHz '' e display sector data '' RR20190217 f combine _SDcard_Init & _readMBR --> Init/CSD/CID/MBR/VOL/FSI/FAT '' g timeout debug... '' RR20190219 h remove SD_CS pull-up check for Start_SDcard (ROM booter) '' +--------------------------------------------------------------------------+ '' RR20190222 003a "ROM_Booter_v33j_SD-003a.spin" copy v33j respin SD ROM code into this ' j use "G" for Prop2 silicon v2 (for Prop_Chk response) '' b add debugging (works), remove "tweek" comments '' c cmd8 debugging '' d report DO when /CS->1 (works) '' e remove CSD/CID/FSI/FAT code (never used anyway) '' free vars vol_begin/fsi_begin/fat_begin/ptn_size, recalc dir_begin '' f '' g add exFAT support??? (mbr/vol/ ) FAT32 wkg '' h call _Run_SDfile instead of _Start_SDcard (prevents MBR/VOL booting) '' exFAT (dir), don't verify nooffats '' ij exFAT wkg except fname '' k wkg inc fname (need to verify length of fname string as 12 chars!!) '' l _sectors <- file_size set in readFILE, fix _validateCSUM mov->add '' m FAT32 & exFAT verified to boot file, MBR(code $80) & MBR(sector/size) '' (need to verify length of fname string as 12 chars!!) ''============================[ CON ]============================================================ CON 'P2-EVAL _XTALFREQ = 20_000_000 ' crystal frequency _XDIV = 4 '\ '\ crystal divider to give 5.0MHz _XMUL = 10 '| 25 MHz '| crystal / div * mul to give 50 MHz _XDIVP = 2 '/ '/ crystal / div * mul /divp to give 25 MHz _XOSC = %10 '15pF ' %00=OFF, %01=OSC, %10=15pF, %11=30pF {{ 'P2D2 _XTALFREQ = 12_000_000 ' crystal frequency _XDIV = 3 '\ '\ crystal divider to give 4.0MHz _XMUL = 12 '| 24 MHz '| crystal / div * mul to give 48 MHz _XDIVP = 2 '/ '/ crystal / div * mul /divp to give 24 MHz _XOSC = %01 'Osc ' %00=OFF, %01=OSC, %10=15pF, %11=30pF }} {{ 'P2D2 _XTALFREQ = 12_000_000 ' crystal frequency _XDIV = 3 '\ '\ crystal divider to give 4.0MHz _XMUL = 14 '| 28 MHz '| crystal / div * mul to give 48 MHz _XDIVP = 2 '/ '/ crystal / div * mul /divp to give 24 MHz _XOSC = %01 'Osc ' %00=OFF, %01=OSC, %10=15pF, %11=30pF }} '------------------------------------------------------------------------------------------------ _XSEL = %11 'XI+PLL ' %00=rcfast(20+MHz), %01=rcslow(~20KHz), %10=XI(5ms), %11=XI+PLL(10ms) _XPPPP = ((_XDIVP>>1) + 15) & $F ' 1->15, 2->0, 4->1, 6->2...30->14 _CLOCKFREQ = _XTALFREQ / _XDIV * _XMUL / _XDIVP ' internal clock frequency _SETFREQ = 1<<24 + (_XDIV-1)<<18 + (_XMUL-1)<<8 + _XPPPP<<4 + _XOSC<<2 ' %0000_000e_dddddd_mmmmmmmmmm_pppp_cc_00 ' setup oscillator _ENAFREQ = _SETFREQ + _XSEL ' %0000_000e_dddddd_mmmmmmmmmm_pppp_cc_ss ' enable oscillator '------------------------------------------------------------------------------------------------ _baud = 115_200 _bitper = (_clockfreq / _baud) << 16 + 7 ' 115200 baud, 8 bits _txmode = %0000_0000_000_0000000000000_01_11110_0 'async tx mode, output enabled for smart output _rxmode = %0000_0000_000_0000000000000_00_11111_0 'async rx mode, input enabled for smart input '------------------------------------------------------------------------------------------------ rx_pin = 63 ' pin serial receiver tx_pin = 62 ' pin serial transmitter spi_cs = 61 ' pin SPI memory select (also sd_ck) spi_ck = 60 ' pin SPI memory clock (also sd_cs) spi_di = 59 ' pin SPI memory data in (also sd_di) spi_do = 58 ' pin SPI memory data out (also sd_do) sd_ck = spi_cs 'pin SD Card clock sd_cs = spi_ck 'pin SD Card select sd_di = spi_di 'pin SD Card MOSI sd_do = spi_do 'pin SD Card MISO '------------------------------------------------------------------------------------------------ _cpufreq = _clockfreq delay1s = _cpufreq ' 1s (xtal * pll) delay10ms = _cpufreq / 100 ' 10ms delay1ms = _cpufreq / 1_000 ' 1ms delay5us = (20_000_000 / 100_000 / 2) - 2 ' 5us @20MHz 100KHz (20MHz/100KHz/2-2=98) ] {{ tweek }} '------------------------------------------------------------------------------------------------ '' +--------------------------------------------------------------------------+ '' | Cluso's LMM_SerialDebugger for P2 (c)2013-2018 "Cluso99" (Ray Rodrick)| '' +--------------------------------------------------------------------------+ '' xxxxxx : xx xx xx xx ... DOWNLOAD: to cog/lut/hub {addr1} following {byte(s)} '' xxxxxx - [xxxxxx] [L] LIST: from cog/lut/hub {addr1} to < {addr2} L=longs '' xxxxxx G GOTO: to cog/lut/hub {addr1} '' Q QUIT: Quit Rom Monitor and return to the User Program '' Lffffffff[.]xxx LOAD: Load file from SD '' Rffffffff[.]xxx RUN: Load & Run file from SD '' TAQOZ: goto TAQOZ '' +--------------------------------------------------------------------------+ '' LMM DEBUGGER - CALL Modes...(not all modes supported) '' +--------------------------------------------------------------------------+ _MODE = $F << 5 ' mode bits defining the call b8..b5 (b4..b0 are modifier options) _SHIFT = 5 ' shr # to extract mode bits _HEX_ = 2 << 5 ' hex... _REV_ = 1 << 4 ' - reverse byte order _SP = 1 << 3 ' - space between hex output pairs '_DIGITS = 7..0 where 8->0 ' - no. of digits to display _LIST = 3 << 5 ' LIST memory line (1/4 longs) from cog/hub _ADDR2 = 1 << 4 ' 1= use lmm_p2 as to-address _LONG_ = 1 << 1 ' 1=display longs xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx _TXSTRING = 4 << 5 ' tx string (nul terminated) from hub _RXSTRING = 5 << 5 ' rx string _ECHO_ = 1 << 4 ' - echo char _PROMPT = 1 << 3 ' - prompt (lmm_x) _ADDR = 1 << 2 ' - addr of string buffer supplied _NOLF = 1 << 1 ' - strip _MONITOR = 7 << 5 ' goto rom monitor '' +--------------------------------------------------------------------------+ '' P2 ROM SERIAL ROUTINES (HUBEXEC) '' +--------------------------------------------------------------------------+ _SerialInit = $fcab8 ' Serial Initialise (lmm_x & lmm_bufad must be set first) _HubTxCR = $fcae4 ' Sends (overwrites lmm_x) _HubTxRev = $fcaec ' Sends lmm_x with bytes reversed _HubTx = $fcaf0 ' Sends lmm_x (can be up to 4 bytes) _HubHexRev = $fcb24 ' Sends lmm_x with bytes reversed as Hex char(s) as defined in lmm_f _HubHex8 = $fcb28 ' Sends lmm_x as Hex char(s) after setting lmm_f as 8 hex chars _HubHex = $fcb2c ' Sends lmm_x as Hex char(s) as defined in lmm_f _HubTxStrVer = $fcb9c ' Sends $0 terminated string at lmm_p address after setting lmm_p=##_str_vers _HubTxString = $fcba4 ' Sends $0 terminated string at lmm_p address _HubListA2H = $fcbc4 ' List/Dump line(s) from lmm_p address to lmm_p2 address after setting lmm_f=#_LIST+_ADDR2 _HubList = $fcbc8 ' List/Dump line(s) from lmm_p address to lmm_p2 address according to lmm_f _HubRx = $fcb10 ' Recv char into lmm_x _HubRxStrMon = $fccc4 ' Recv string into lmm_bufad address after setting prompt=lmm_x=#"*" & params=lmm_f=#_RXSTRING+_ECHO_+_PROMPT _HubRxString = $fcccc ' Recv string into lmm_p/lmm_bufad address according to params in lmm_f _HubMonitor = $fcd78 ' Calls the Monitor; uses lmm_bufad as the input buffer address _RdLongCogHub = $fcf34 ' read cog/lut/hub long from lmm_p address into lmm_x, then lmm_p++ _str_vers = $fd014 ' locn of hub string, $0 terminated '' +--------------------------------------------------------------------------+ '' HUB ADDRESSES '' +--------------------------------------------------------------------------+ _HUBROM = $FC000 ' ROM $FC000 _HUBBUF = $FC000 ' overwrite Booter _HUBBUFSIZE = 80 ' RxString default size for _HUBBUF '' +--------------------------------------------------------------------------+ {{ ''============[ COG VARIABLES $1E0-$1EF - MONITOR]============================= ''-------[ LMM parameters, etc ]----------------------------------------------- lmm_x = $1e0 ' parameter passed to/from LMM routine (typically a value) lmm_f = $1e1 ' parameter passed to LMM routine (function options; returns unchanged) lmm_p = $1e2 ' parameter passed to/from LMM routine (typically a hub/cog ptr/addr) lmm_p2 = $1e3 ' parameter passed to/from LMM routine (typically a 2nd hub/cog address) lmm_c = $1e4 ' parameter passed to/from LMM routine (typically a count) ''-------[ LMM additional workareas ]------------------------------------------ lmm_w = $1e5 ' workarea (never saved - short term use between calls, except _HubTx) lmm_tx = $1e6 ' _HubTx lmm_hx = $1e7 ' _HubHex/_HubString lmm_hx2 = $1e8 ' _HubHex lmm_hc = $1e9 ' " lmm_lx = $1ea ' _HubList lmm_lf = $1eb ' " lmm_lp = $1ec ' " lmm_lp2 = $1ed ' " lmm_lc = $1ee ' " lmm_bufad = $1ef ' _HubRxString }} '' +--------------------------------------------------------------------------+ '' ASCII equates '' +--------------------------------------------------------------------------+ _CLS_ = $0C _BS_ = $08 _LF_ = $0A _CR_ = $0D _TAQOZ_ = $1B ' goto TAQOZ '' +--------------------------------------------------------------------------+ DAT orgh 0 org 0 '+-------[ Set Xtal ]----------------------------------------------------------+ entry hubset #0 ' set 20MHz+ mode hubset ##_SETFREQ ' setup oscillator waitx ##20_000_000/100 ' ~10ms hubset ##_ENAFREQ ' enable oscillator '+-----------------------------------------------------------------------------+ waitx ##_clockfreq*5 ' just a delay to get pc terminal running ''-------[ Start Serial ]------------------------------------------------------ mov lmm_bufad, ##_HUBBUF ' locn of hub buffer for serial routine mov lmm_x, ##_bitper ' sets serial baud call #_SerialInit ' initialise serial ''+----------------------------------------------------------------------------+ ''+ Display a String (in HUB, $00 terminated) + ''+----------------------------------------------------------------------------+ mov lmm_p, ##hubstring ' must be in hub! call #_HubTxString ''----------------------------------------------------------------------------- ' Load/Run default filename incl MBR/VOL jmp #@_start_sdcard '????????????????????????????????????????? { ' Load/Run default filename excluding MBR/VOL mov fname, ##_fname1a ' copy _fname1 -> fname mov fname+1, ##_fname1b ' mov fname+2, ##_fname1c ' call #@_Run_SDfile ' search/load/run file } mov lmm_p, ##str_returned ' must be in hub! call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_z mov lmm_x, ##$205A ' "Z " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nz mov lmm_x, ##$205A4E ' "NZ " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< jmp #$ ''----------------------------------------------------------------------------- try_serial mov lmm_p, ##str_ser ' must be in hub! call #_HubTxString jmp #$ '+-----------------------------------------------------------------------------+ x3333_0000 long $3333_0000 x7777_0000 long $7777_0000 '+-----------------------------------------------------------------------------+ '------------------------------------------------------------------------------------------------ DAT ''============[ COG VARIABLES - SD BOOT]======================================== org $1C0 ' place the variables in cog $1C0-$1DF cmdout res 1 ' The 8b CMDxx | $40 cmdpar res 1 ' The 32b parameters cmdcrc res 1 ' The 8b CRC (must be valid for CMD0 & CMD8) cmdpar2 res 1 ' SDV1=$0, SDV2=$40000000 cmdtype res 1 ' reply is R1=1, R3=3, R7=7, else 0 reply res 1 ' R1 reply (moved to replyR1 when R3/R7 32b reply here) replyR1 res 1 ' R1 reply (8b saved when R3/R7 32b reply follows) dataout res 1 ' 8/32 bit data being shifted out bytescnt res 1 ' #bytes to send/recv bitscnt res 1 ' #bits to be shifted in/out ctr1 res 1 timeout res 1 ' = starttime + delay _AA55 res 1 ' used to store $AA55 to validate MBR/VOL/FSI skiprun res 1 ' 1= skip load/run mbr/vol & load/no-run fname '\ 1=SDV1, 2=SDV2(byte address), 3=SDHC/SDV2(block address) blocksh res 1 '/ block shift 0/9 bits clustersh res 1 ' sectors/cluster SHL 'n' bits xx_vol_begin res 1 ' Ptn0: first sector of PTN xx_fsi_begin res 1 ' Ptn0: sector of file system info file_size res 1 ' file_size (sectors) dir_begin res 1 ' Ptn0: first sector of DATA is DIR table dat_begin res 1 ' Ptn0: first sector of file's DATA ptn_type res 1 ' Ptn0: type $0B/$0C=FAT32, $07=exFAT/NTFS (was ptn_size) _bufad res 1 _blocknr res 1 _sectors res 1 _entries res 1 bufad res 1 ' ptr sector buffer blocknr res 1 ' sector# fname res 3 ' 8+3+1 _hubdata res 1 fit $1E0 ''============[ COG VARIABLES - MONITOR]======================================== org $1E0 ' place the variables in cog $1E0-$1EF ''-------[ LMM parameters, etc ]------------------------------------------------ lmm_x res 1 ' parameter passed to/from LMM routine (typically a value) lmm_f res 1 ' parameter passed to LMM routine (function options; returns unchanged) lmm_p res 1 ' parameter passed to/from LMM routine (typically a hub/cog ptr/addr) lmm_p2 res 1 ' parameter passed to/from LMM routine (typically a 2nd hub/cog address) lmm_c res 1 ' parameter passed to/from LMM routine (typically a count) ''-------[ LMM additional workareas ]------------------------------------------- lmm_w res 1 ' workarea (never saved - short term use between calls, except _HubTx) lmm_tx res 1 ' _HubTx lmm_hx res 1 ' _HubHex/_HubString lmm_hx2 res 1 ' _HubHex lmm_hc res 1 ' " lmm_lx res 1 ' _HubList lmm_lf res 1 ' " lmm_lp res 1 ' " lmm_lp2 res 1 ' " lmm_lc res 1 ' " lmm_bufad res 1 ' _HubRxString fit $1F0 ''=======[ ^^^^^ End of COG Variables ^^^^^ ]=================================== '' +--------------------------------------------------------------------------+ '' | Cluso's Minimal SD Boot Test for P2 (c)2012-2018 "Cluso99" (Ray Rodrick)| '' +--------------------------------------------------------------------------+ '' RR20180505 v128a add into ROM_v131b ''============================[ CON ]============================================================ CON _csum = ("P" + "r"<<8 + "o"<<16 + "p"<<24) ' "Prop" checksum (reversed) _csum2 = ("P" + "r"<<8 + "o"<<16 + "P"<<24) ' "ProP" checksum (reversed) _fname1a = ("_" + "B"<<8 + "O"<<16 + "O"<<24) '\\ filename... _fname1b = ("T" + "_"<<8 + "P"<<16 + "2"<<24) '|| 8.3 +$00 _fname1c = ("B" + "I"<<8 + "X"<<16 + $00<<24) '// _fname2c = ("B" + "I"<<8 + "Y"<<16 + $00<<24) '// mbr_begin = 0 ' first sector of disk $0000_0000 '------------------------------------------------------------------------------------------------ ' COG & LUT & HUB ADDRESSES '------------------------------------------------------------------------------------------------ hubdata = $0_0000 ' expands up (512byte sectors) max_size = (512-16)*1024 ' max file_size(bytes) that can be loaded cog_start0 = $000 ' cog code start cog_len = 512-16 ' cog code length cog_len80 = 512/4 ' 512 bytes (sector) '------------------------------------------------------------------------------------------------ ' SD Commands & Responses... '------------------------------------------------------------------------------------------------ ' Command Argument Response/Data Description CMD0 = 0 +$40 ' 0 R1 - GO_IDLE_STATE *Reqs valid CRC ' CMD1 = 1 +$40 ' 0 R1 - SEND_OP_COND ACMD41 = 41 +$40 ' $4000_0000 R1 - APP_SEND_OP_COND *Reqs CMD55 first CMD8 = 8 +$40 ' 0 R1+R7 - SEND_IF_COND *Reqs valid CRC CMD9 = 9 +$40 ' 0 R1 Y SEND_CSD CMD10 = 10 +$40 ' 0 R1 Y SEND_CID ' CMD12 = 12 +$40 ' 0 R2 - STOP_TRANSMISSION CMD16 = 16 +$40 ' BlkLen[31:0] R1 - SET_BLOCKLEN CMD17 = 17 +$40 ' Addr[31:0] R1 Y READ_SINGLE_BLOCK ' CMD18 = 18 +$40 ' Addr[31:0] R1 Y READ_MULTIPLE_BLOCK ' CMD23 = 23 +$40 ' NoBlks[15:0] R1 - SET_BLOCK_COUNT ' ACMD23 = 23 +$40 ' NoBlks[22:0] R1 - SET_WR_BLOCK_ERASE_COUNT *Reqs CMD55 first ' CMD24 = 24 +$40 ' Addr[31:0] R1 Y* WRITE_BLOCK ' CMD25 = 25 +$40 ' Addr[31:0] R1 Y* WRITE_MULTIPLE_BLOCK CMD55 = 55 +$40 ' 0 R1 - APP_CMD *Prefix for ACMD41/ACMD23 CMD58 = 58 +$40 ' 0 R1+R3 - READ_OCR DAT ''################################################################################################ ''## SD Card - HUBEXEC code... ## ''################################################################################################ orgh $1_0000 '+-------[ SD: Initialise/Locate/Load/Run a file from SD ]---------------------+ <--- SD: init/locate/load/run a file ---> '+ On Entry: + '+ fname[3]: filename[11] 8+3 without "." (will be $0 terminated) + '+ Call Format: + '+ CALL #@_Run_SDfile ' + < call: init/locate/load/run a file > '+ On Return: + '+ "NZ" if error, else does not return + '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ _Start_SDcard mov skiprun, #0 ' load/run MBR/VOL code call #@_SDcard_Init0 ' Init/CSD/CID/MBR/VOL/FSI/FAT (skiprun=0) if_e call #@_readDIR ' read directory for filenames '' mov skiprun, #0 ' load/run (already 0) if_e call #@_readFILE ' read/load/run the file call #@_releaseDO ' /CS=1, send CLKs, tristate CS/CK/DI/DO JMP #try_serial ' failed: so go back and try serial '+-----------------------------------------------------------------------------+ _Run_SDfile call #@_SDcard_Init1 ' Init/CSD/CID/MBR/VOL/FSI/FAT (skiprun=1) if_e call #@_searchDIR ' search dir for mov skiprun, #0 ' load/run (skiprun=0) _Loadit ' if_e call #@_readFILE ' read/load/[run] the file call #@_releaseDO ' /CS=1, send CLKs, tristate CS/CK/DI/DO RET ' return "NZ" = failed, "Z" if loaded ok '+-----------------------------------------------------------------------------+ _Load_SDfile call #@_SDcard_Init1 ' Init/CSD/CID/MBR/VOL/FSI/FAT (skiprun=1) if_e call #@_searchDIR ' search dir for '' mov skiprun, #1 ' load, do not run (already 1) jmp #@_Loadit ' if Z go read/load file '+-----------------------------------------------------------------------------+ '+-------[ SD Card Initialisation ]--------------------------------------------+ <--- SD initialisation ---> '+ On Entry: + '+ Call Format: + '+ CALL #@_SDcard_Init ' + < call: sd initialise > '+ On Return: + '+ hub $0 = CSD[16] + CID[16] ' csd/cid data + '+ Returns "Z" if ok, "NZ" if error + '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ SD/SDHC/sdxc SPI Initialisation + '+-----------------------------------------------------------------------------+ '+ Send >74 clocks with /CS=1 & DI=1 starting & ending with CLK=0 + '+-----------------------------------------------------------------------------+ _SDcard_Init1 mov skiprun, #1 wz ' do not load/run MBR/VOL code '--v33k-- drvl #sd_cs '\ ensure we have an SD card waitx #30*1 '| wait >1us fltl #sd_cs '| /CS=tristate waitx #30*5 '| wait >5us testp #sd_cs wc '| /CS=1? pullup? if_nc RET '/ "NZ"=failed (pullup) _SDcard_Init0 mov _hubdata, #hubdata ' init hub data ptr=$0 drvh #sd_cs ' /CS=1 & output drvl #sd_ck ' CLK=0 & output drvh #sd_di ' DI =1 & output waitx #delay5us ' rep @.rep,#(96*2) ' outnot #sd_ck '\ CLK=0-->1-->0 waitx #delay5us '/ 5us @20MHz 100KHz (20MHz/100KHz/2-2=98) .rep ' /CS=1 & CLK=0 (idle) '+-----------------------------------------------------------------------------+ '+ Software Reset: + '+ CMD0, PAR=$0, CRC=$95, REPLY=R1($01) + '+-----------------------------------------------------------------------------+ .Command0 getct timeout '\ set timeout up to CMD9 add timeout, ##delay10ms '/ mov ctr1, #10 ' try a few times .again0 mov cmdout, #CMD0 mov cmdpar, #0 mov cmdcrc, #$95 '+-----------------------------------------------------------------------------+ call #@_cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ if_nc add timeout, ##delay1s ' increase timeout to 1s '\ $01(idle): SD/MMC, not fully validated if_nc jmp #.Command8 '/ $00(good): (dane card response) '+-----------------------------------------------------------------------------+ waitx #delay5us ' delay 5us @20MHz djnz ctr1, #.again0 ' n: try again? jmp #@_fail00 ' '+=============================================================================+ ' we know we now have an SD/MMC card but its not fully validated yet... '+-----------------------------------------------------------------------------+ '+ Check Voltage: + '+ CMD8, PAR=$1AA, CRC=$87, REPLY=R1($01)+R7($xx1AA) ($05=try SDV1) + '+-----------------------------------------------------------------------------+ .Command8 mov cmdout, #CMD8 mov cmdpar, #$1AA mov cmdcrc, #$87 '+-----------------------------------------------------------------------------+ call #@_cmdR1R7 ' /CS=0, send cmd, recv R1+R7, /CS=1 '+-----------------------------------------------------------------------------+ '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, replyR1 ' R1 reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply ' R7 reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_c_or_z jmp #.illegal ' j if <> $01 (not idle) .idle and reply, ##$FFF '\ cmp reply, #$1AA wz '/ R7[11:0]=$1AA ? mov cmdpar2, ##$40000000 ' preset for SDV2 if_ne jmp #@_fail98 ' n: unknown R7 jmp #.Command55 ' y: CMD55+ACMD41($4000_0000) .illegal cmp replyR1, #$05 wz ' $05(illegal cmd) ? if_ne jmp #@_fail08 ' <>$01/$05 (not idle/illegal) mov cmdpar2, #0 ' try SDV1 ' CMD55+ACMD41($0) fall thru '+-----------------------------------------------------------------------------+ '+ Prefix to ACMD41 & ACMD23: + '+ CMD55, PAR=$0, CRC=$xx, REPLY=R1($01) + '+-----------------------------------------------------------------------------+ .Command55 mov cmdout, #CMD55 ' mov cmdpar, #0 ' '+-----------------------------------------------------------------------------+ call #@_cmdRZA41 ' /CS=0, send cmd, recv R1, /CS=0(ena) '+-----------------------------------------------------------------------------+ if_c_or_z jmp #@_fail55 ' <>$01 (not idle) ' fall thru '+-----------------------------------------------------------------------------+ '+ Check SDV1/SDV2: (follows CMD55) + '+ ACMD41, PAR=$0, CRC=$xx, REPLY=R1($00) SD-V1 + '+ ACMD41, PAR=$40000000, CRC=$xx, REPLY=R1($00) SD-V2 + '+-----------------------------------------------------------------------------+ .CommandA41 mov cmdout, #ACMD41 ' mov cmdpar, cmdpar2 ' SDV1=0 / SDV2=$40000000 '+-----------------------------------------------------------------------------+ call #@_cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ if_nc_and_nz jmp #.Command55 ' =$01(busy): CMD55+CMD41 again if_c jmp #@_fail41 ' <>$00/$01: error cmp cmdpar2, #0 wz ' SDV1 ? if_z mov blocksh, #9 ' y: #1 SDV1(byte address) if_z jmp #.Command16 ' y: SDV1 does not use CMD58 ' SDV2 fall thru '+-----------------------------------------------------------------------------+ '+ Check OCR CCS bit: + '+ CMD58, PAR=$0, CRC=$xx, REPLY=R1($00)+R3(b30=1) + '+-----------------------------------------------------------------------------+ .Command58 mov cmdout, #CMD58 ' SDHC ? mov cmdpar, #0 ' '+-----------------------------------------------------------------------------+ call #@_cmdR1R3 ' /CS=0, send cmd, recv R1+R3, /CS=1 '+-----------------------------------------------------------------------------+ if_c_or_nz jmp #@_fail58 ' <>$00(good): error testbn reply, #30 wz ' bit30=CCS=1? $40000000? if_z mov blocksh, #9 ' n: #2 SDV2(byte address) if_nz mov blocksh, #0 ' y: #3 SDHC/SDV2(block address) ' SDV2(byte) fall thru '+-----------------------------------------------------------------------------+ '+ Force block size to 512 bytes: + '+ CMD16, PAR=$200, CRC=$xx, REPLY=R1($00) + '+-----------------------------------------------------------------------------+ .Command16 mov cmdout, #CMD16 ' force blocksize=512bytes decod cmdpar, #9 ' $200 = 512 bytes '+-----------------------------------------------------------------------------+ call #@_cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ if_nc_and_nz jmp #.Command16 ' =$01(idle): again if_c_or_nz jmp #@_fail16 ' <>$00(good): error '+-----------------------------------------------------------------------------+ mov _bufad, _hubdata ' where to store data mov bufad, _bufad ' where to store CSD/CID '+-----------------------------------------------------------------------------+ ' fall thru '+-------[ SD: Read MBR/VOL/FSI/FAT ]------------------------------------------+ <--- SD: read mbr/vol/fsi/fat ---> '+ On Entry: + '+ skiprun: #0 = load/run boot code if found on MBR/VOL + '+ #1 = do not load/run boot code on MBR/VOL + '+ Call Format: + '+ CALL #@_readMBR ' + < call: read mbr/vol/fsi/fat > '+ On Return: + '+ DOES NOT RETURN if skiprun = #0 and code found on MBR/VOL + '+ Returns: "Z" if ok, "NZ" if error + '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Read MBR/VBR (Sector 0): + '+-----------------------------------------------------------------------------+ ._readMBR mov _blocknr, #mbr_begin ' VBR/MBR = SECTOR 0 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_mbr '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #@_readSECTOR ' read sector skip skiprun ' skips next instr if #1 call #@_validateCSUM ' valid -> load & run '+-----------------------------------------------------------------------------+ '+ Validate MBR (PTN0 table & signature) + '+ +$1BE[16] = = Ptn0 Table... + '+ verify +$1BE+$0[1] = $00/$80 = Ptn0 State + $1BE '+ verify +$1BE+$4[1] =$0B/0C/07= Ptn0 Type --> ptn_type + $1C2 '+ calc +$1BE+$8[4] = = Ptn0 StartSector# vol_begin + $1C6 '+ x calc +$1BE+$C[4] = = Ptn0 SectorSize ptn_size + $1CA '+ verify +$1FE[2] = $55AA = signature + $1FE '+-----------------------------------------------------------------------------+ ._validateMBR mov bufad, _bufad ' MBR hub addr mov _AA55, ##$AA_55 ' initialise (reversed) add bufad, #($1C2) ' offset to ptn_type rdbyte ptn_type, bufad ' ptn_type $1C2 cmp ptn_type, #$0C wz ' $0C=FAT32(LBA) if_ne cmp ptn_type, #$0B wz ' $0B=FAT32(CHS) if_ne cmp ptn_type, #$07 wz ' $07=exFAT/NTFS sub bufad, #($1C2-$1BE) ' offset to PTN0 state rdbyte reply, bufad ' ptn_state $1BE if_e and reply, #$7F wz ' $00/80? inactive/active add bufad, #($1FE-$1BE) ' offset to $55AA signature rdword reply, bufad ' we read it reversed! $1FE if_e cmp reply, _AA55 wz ' $55AA? if_ne jmp #@_fail_mbr ' sub bufad, #($1FE-$1C6) ' offset to start sector rdlong dir_begin, bufad ' dir_begin <= vol_begin $1C6 '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Read VOL (Sector x): + '+-----------------------------------------------------------------------------+ ._readVOL mov _blocknr, dir_begin ' VOL SECTOR# '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_vol '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #@_readSECTOR ' read sector skip skiprun ' skips next instr if #1 call #@_validateCSUM ' if valid -> load & run '+-----------------------------------------------------------------------------+ ' Validate FAT32 VOL... FAT32 + ' verify +$00B[2] = 512 = #Bytes/Sector + ' calc +$00D[1] = = #Sectors/Cluster 64? --> clustersh + ' x calc +$00E[2] = #ResvSectors PTN0RESV + ' x verify +$010[1] = 2 = #NoOfFATs PTN0NUMFATS + ' x ??? +$020[4] = #Sectors/PTN =ptn_size + ' x calc +$024[4] = #Sectors/FAT PTN0SECFAT + ' x calc +$030[2] = #FileSystemInfo fsi_begin + ' verify +$1FE[2] = $55AA = signature + ' + ' x calc fat_begin = vol_begin + PTN0RESV + ' calc dir_begin = vol_begin + PTN0RESV + (PTN0SECFAT * PTN0NUMFATS)+ '+-----------------------------------------------------------------------------+ ' Validate exFAT VOL... exFAT + ' x ??? +$003[8] = "EXFAT " + ' calc +$058[4] = #Cluster Offset clusteroffset + ' verify +$06C[1] = 9 = #Bytes/Sector (512) + ' save +$06D[1] = 8 = #Sectors/Cluster (256) --> clustersh + ' x verify +$06E[1] = 1 = #NoOfFATs + ' verify +$1FE[2] = $55AA = signature + ' + ' calc dir_begin = vol_begin + ClusterOffset + (2 << clustersh) + '+-----------------------------------------------------------------------------+ ._validateVOL mov bufad, _bufad ' VOL hub locn testb ptn_type, #3 wc ' C if $0B/$0C=FAT32 else exFAT add bufad, #($1FE) '\ offset to $55AA signature rdword reply, bufad '| we read it reversed! cmp reply, _AA55 wz '/ $55AA? if_c sub bufad, #($1FE-$0B) '\ offset to bytes/sector FAT32 if_c rdword reply, bufad '| read " if_c_and_z cmp reply, ##512 wz '/ 512? " if_nc sub bufad, #($1FE-$6C) '\ offset to bytes/sector exFAT if_nc rdbyte reply, bufad '| read " if_nc_and_z cmp reply, #9 wz '/ 9=512? " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_check '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_c mov lmm_x, ##$2043 ' "C " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nc mov lmm_x, ##$20434E ' "NC " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_z mov lmm_x, ##$205A ' "Z " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nz mov lmm_x, ##$205A4E ' "NZ " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, bufad '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nz jmp #@_fail_vol ' "NZ"=failed if_c add bufad, #($0D-$0B) '\ offset to #Sectors/Cluster FAT32 if_nc add bufad, #($6D-$6C) '| exFAT rdbyte clustersh, bufad '| read FAT32/exFAT if_c encod clustersh '/ calc as shift left 'n' FAT32 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_check '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_c mov lmm_x, ##$2043 ' "C " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nc mov lmm_x, ##$20434E ' "NC " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_z mov lmm_x, ##$205A ' "Z " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nz mov lmm_x, ##$205A4E ' "NZ " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, bufad '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, clustersh '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ' currently dir_begin = vol_begin ' FAT32: dir_begin = vol_begin + PTN0RESV + (PTN0SECFAT * PTN0NUMFATS) ' exFAT: dir_begin = vol_begin + ClusterOffset + (2 << clustersh) if_c add bufad, #($0E-$0D) '\ offset to #ResvSectors FAT32 if_c rdword reply, bufad '| read " if_c add dir_begin, reply '/ <=fat_begin " if_nc sub bufad, #($6D-$58) '\ offset to clusteroffset exFAT if_nc rdlong reply, bufad '| read " if_nc add dir_begin, reply '/ + clusteroffset " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_check '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_c mov lmm_x, ##$2043 ' "C " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nc mov lmm_x, ##$20434E ' "NC " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_z mov lmm_x, ##$205A ' "Z " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nz mov lmm_x, ##$205A4E ' "NZ " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, bufad '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_c add bufad, #($24-$0E) '\ offset to #Sectors/FAT FAT32 if_c rdlong reply, bufad '| read " if_nc decod reply, clustersh '| 1 << clustersh exFAT add dir_begin, reply '| + (2 * 'relpy') FAT32/exFAT add dir_begin, reply '/ <=dir_begin " " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nc jmp #.skip '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_check '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_c mov lmm_x, ##$2043 ' "C " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nc mov lmm_x, ##$20434E ' "NC " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_z mov lmm_x, ##$205A ' "Z " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nz mov lmm_x, ##$205A4E ' "NZ " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, bufad '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .skip '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '+-----------------------------------------------------------------------------+ _RET_ MODZ _set wz ' "Z" = success '+=============================================================================+ _fail00 _fail98 _fail08 _fail55 _fail41 _fail58 _fail16 _fail_mbr _fail_vol '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_fail '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< _RET_ MODCZ _set,_clr wcz ' C & NZ = failed '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ Read DIR (n Sectors): Search for "<_fname/_fname2>" + '+-----------------------------------------------------------------------------+ _readDIR mov fname, ##_fname1a ' copy _fname1 -> fname mov fname+1, ##_fname1b ' mov fname+2, ##_fname1c ' call #@_searchDIR ' search dir for if_e RET ' return "Z" = found mov fname+2, ##_fname2c ' new fname ext call #@_searchDIR ' search dir for RET ' return "Z" = found, else "NZ" '+=============================================================================+ '+-------[ SD: Search Root Directory for <_fname> entry ]----------------------+ <--- SD: search root directory ---> '+ On Entry: + '+ fname[3]: filename[11] 8+3 without "." + '+ Call Format: + '+ CALL #@_searchDIR ' + < call: search root directory > '+ On Return: + '+ "Z" if found, and sets + '+ dat_begin = first native sector of file's data + '+ _sectors = file size in bytes + '+ "NZ" if not found / error + '+-----------------------------------------------------------------------------+ _searchDIR and fname+2, ##$00FFFFFF ' 12th char must be $00 mov _blocknr, dir_begin ' DIR SECTOR# decod _sectors, clustersh ' max sectors to scan (1 cluster) '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_DIR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .search_next call #@_readSECTOR ' read sector '+-----------------------------------------------------------------------------+ '+ Walk Directory: (read DIR sectors) + '+ 16 x 32byte DIR(fname) entries per DIR sector + '+ +$00[1] = $00 = empty + '+ => $80 = deleted file + '+ search +$00[11] = 8.3 filename + '+ verify +$0B[1] = FileAttrib AND $D8,check $00 + '+ $01=read,02=hidden,04=system,08=volume,0F=longfile,10=dir,20=archive+ '+ calc +$14[2] = FAT32: 1st cluster# HI -\-> cluster + '+ calc +$1A[2] = FAT32: 1st cluster# LO -/ + '+ calc +$1C[4] = FAT32: FileSize in bytes --> file_size + '+ calc dat_begin = dir_begin + ((cluster-2)<<6) + '+-----------------------------------------------------------------------------+ ' scan dir sector for files... .walk_dir mov _entries, #16 ' 16*32byte file entries mov bufad, _bufad ' dir hub locn testb ptn_type, #3 wc ' C if $0B/$0C=FAT32 else exFAT .scan rdlong reply, bufad wz '\ check this entry, $0=empty '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_c_and_nz jmp #.fat32 '| n: if_nc_and_nz jmp #.exfat '| n: _RET_ MODZ _clr wz '/ return "NZ" = not found ' ================================================ ' FAT32: scan this entry for filename, etc... .fat32 cmp reply, fname wz '\ check fname... add bufad, #4 '| rdlong reply, bufad '| if_e cmp reply, fname+1 wz '| add bufad, #4 '| rdlong reply, bufad '| and reply, ##$D8FFFFFF '| check atts b7+6+4+3 if_e cmp reply, fname+2 wz '| if_e jmp #.found32 '/ found! add bufad, #(32-8) ' next entry djnz _entries, #.scan ' "NZ" not found this sector '+-----------------------------------------------------------------------------+ add _blocknr, #1 ' next sector# _RET_ djnz _sectors, #.search_next ' return "NZ" = not found '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ FAT32: cluster = +$14[2] +$1A[2] + '+ filesize = +$1C[4] + '+ sector = ((cluster-2)<12 force length error! ??????????????????????????????????? jmp #.next ' next entry should be $C1 '+-----------------------------------------------------------------------------+ .rec_C1 add bufad, #($02-$00) ' offset to fname (unicode) call #_unicode ' convert to ascii cmp reply, fname wz ' "_BOO" '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, bufad '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, fname '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_unicode ' convert to ascii if_e cmp reply, fname+1 wz ' "T_P2" '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, bufad '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, fname+1 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_unicode ' convert to ascii shr reply, #8 ' remove "." and 12th char =$00 if_e cmp reply, fname+2 wz ' ".BIX" '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, bufad '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, fname+2 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_ne sub bufad, #(3*8)+2 ' back to start this entry if_ne jmp #.next ' and get next entry '+-----------------------------------------------------------------------------+ ' found ' convert file start to sector# sub dat_begin, #4 '\ correct cluster addr(-4) shl dat_begin, clustersh '| convert to sector <<8 add dat_begin, dir_begin '/ +base ' read filesize(bytes) '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, dat_begin '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, file_size '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< _RET_ mov _sectors, file_size ' return "Z"=found '+=============================================================================+ _unicode mov ptra, bufad ' ptr to fname chars rdlong reply, ptra++ ' read 2 unicode chars movbyts reply, #%11_01_10_00 ' put in 2 low bytes rdlong replyR1, ptra++ ' read 2 unicode chars movbyts replyR1, #%10_00_11_01 ' put in 2 hi bytes setq ##$FFFF_0000 muxq reply, replyR1 ' collect 4 bytes _RET_ mov bufad, ptra ' update ptr '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ Validate MBR/VOL CSUM $080-$17F="Prop". If valid, copy to Cog & Run + '+-----------------------------------------------------------------------------+ _validateCSUM mov bufad, _bufad ' base read add bufad, #$17C ' +$17C: offset to Prop/ProP ID rdlong reply, bufad ' cmp reply, ##_csum wz ' ="Prop"? if_e jmp #@_success80 ' y: go load/run it cmp reply, ##_csum2 wz ' ="ProP"? sector/size? if_ne RET ' return "NZ" = not found ' ---------------------------------------- sub bufad, #($17C-$174) ' +$174: offset to sector start rdlong dat_begin, bufad ' set: file sector start add bufad, #($178-$174) ' +$178: offset to length(bytes) rdlong file_size, bufad ' set: file length(bytes) ' ' fall thru to _readFILE '+-------[ SD: Read File ]-----------------------------------------------------+ <--- SD: load/run file ---> '+ On Entry: + '+ dat_begin = first native sector of file's data + '+ file_size = file size in bytes + '+ Call Format: + '+ CALL #@_readFILE ' + < call: load/run file > '+ On Return: + '+ "NZ" if error, else does not return + '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Read FILE (n Sectors): File "<_fname/_fname2>" + '+-----------------------------------------------------------------------------+ _readFILE mov _blocknr, dat_begin ' DAT SECTOR# mov _sectors, file_size ' size(bytes) ' convert _sectors = file_size (bytes) into sectors to read fle _sectors, ##max_size ' limit max size to load add _sectors, #511 ' +sector if extra bytes shr _sectors, #9 ' sectors=file_size/512 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_file '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, dat_begin '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, _sectors '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, file_size '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ' load file's data - multiple sector(s) call #@_readSECTOR ' read sector djz _sectors, #.done .nextsector call #@_readnxtSECTOR ' read sector(s) djnz _sectors, #.nextsector .done '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_load '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< cmp skiprun, #1 wz ' skip running? if_e RET ' return "Z" = successful load ' else fall thru & run '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ' <-- NZ: load Cog 496 longs & jmp #$000 _success80 ' <-- Z: load cog 128 longs & jmp #$020 '''' call #@_releaseDO ' /CS=1, send CLKs, tristate CS/CK/DI/DO '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_ne mov reply, #cog_len-1 ' set to copy whole cog (496 longs) if_e mov reply, #cog_len80-1 ' set to copy 512 bytes (128 longs) setq reply ' length -1 rdlong cog_start0, _hubdata ' copy loaded code into cog '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_run '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #check_DO '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_z mov lmm_x, ##$205A ' "Z " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nz mov lmm_x, ##$205A4E ' "NZ " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_ne jmp #$0 ' NZ: execute loaded cog code jmp #$020 ' Z: execute loaded cog code from $080+ (MBR/VOL) '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ '+-----------------------------------------------------------------------------+ '+ Read Sector: + '+-----------------------------------------------------------------------------+ _readnxtSECTOR add _blocknr, #1 ' next sector# _readnxtSLOT add _bufad, ##512 ' next data slot _readSECTOR mov blocknr, _blocknr ' sector# mov bufad, _bufad ' where to store data '+-----------------------------------------------------------------------------+ '+ Read Block/Sector: (512 bytes) + '+ CMD17, PAR=blocknr, CRC=$xx, REPLY=R1($??) +n*$FF +($FE+block+CRC16) + '+-----------------------------------------------------------------------------+ .Command17 mov bytescnt, ##512 ' read block (no. bytes) mov cmdout, #CMD17 ' mov cmdpar, blocknr ' shl cmdpar, blocksh ' <<0 or <<9 '+-----------------------------------------------------------------------------+ call #@_readBLOCK ' read 512 bytes '+-----------------------------------------------------------------------------+ RET ' "Z"=success, "NZ"=failed '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ Read Block/Sector: (512 bytes) + '+ CMD9, PAR=$0, CRC=$xx, REPLY=R1($00) + '+ CMD10, PAR=$0, CRC=$xx, REPLY=R1($00) + '+ CMD17, PAR=blocknr, CRC=$xx, REPLY=R1($??) +n*$FF +($FE+block+CRC16) + '+-----------------------------------------------------------------------------+ _readREG mov bytescnt, #16 ' CMD9,10: CSD,CID register mov cmdpar, #0 ' PAR=$0, 16 bytes _readBLOCK ' CMD17: PAR=sector, 512 bytes getct timeout '\ set timeout for cmd9,10,17 add timeout, ##delay1s '/ '+-----------------------------------------------------------------------------+ call #@_cmdRZtoken ' /CS=0, send cmd, recv R1, /CS=0(ena) if_nz RET '<>$00=error="NZ"=failed '+-----------------------------------------------------------------------------+ call #@_getreply ' n*$FF+$FE cmp reply, #$FE wz ' $FE=valid Data Token if_nz RET '<>$FE=error="NZ"=failed '+-----------------------------------------------------------------------------+ '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, bufad ' hub addr '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< or lmm_p, ##$10_0000 ' force hub addr '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p2, lmm_p ' calc to addr '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< add lmm_p2, bytescnt ' '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< sub lmm_p2, #1 ' '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .readbyte call #@_recvbyte ' read data byte wrbyte reply, bufad ' save byte add bufad, #1 ' bufad++ djnz bytescnt, #.readbyte ' byte-- call #@_recvbyte ' read CRC16 1/2 call #@_recvbyte ' read CRC16 2/2 ' NOTE: CRC16 not checked - do we want to do this? ?????????? '' outl #sd_ck ' CLK=0 (idle) already=0 '' outh #sd_cs '/CS=1(disable) '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #check_DO ' '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubListA2H ' lmm_p & lmm_p2 set above! '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< _RET_ MODZ _set wz ' "Z" = success '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ SEND: CMDx, PARx, CRCx, GET REPLY + '+-----------------------------------------------------------------------------+ _cmdRZA41 ' CMD55: R1 response _cmdRZtoken ' CMD9,10,17,24: R1+$FE response mov cmdtype, #1 ' returns w /CS=0(ena) jmp #@_cmdxx ' _cmdR1R3 ' CMD58: R1+R3 response _cmdR1R7 ' CMD8: R1+R7 response _cmdR1 ' CMD0,A41,16: R1 response mov cmdtype, #0 ' returns w /CS=1(disabled) _cmdxx ' '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_cmd '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, cmdout ' cmd '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< and lmm_x, #$3F '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_f, #_HEX_+2 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, cmdpar ' par '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, cmdcrc ' cmd '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_f, #_HEX_+2 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #")" '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '+-----------------------------------------------------------------------------+ outl #sd_cs ' /CS=0 (enable) '+-----------------------------------------------------------------------------+ call #@_sendFF ' send $FF byte first mov dataout, cmdout ' CMD call #@_sendbyte ' send cmd byte mov dataout, cmdpar ' Parameter call #@_sendlong ' send 4 bytes (MSB first) mov dataout, cmdcrc ' CRC call #@_sendbyte ' send crc byte '+-----------------------------------------------------------------------------+ call #@_getreply ' recv R1/R1+R3/R1+R7/RZ..+Token '+-----------------------------------------------------------------------------+ '' outl #sd_ck ' CLK=0 (idle) already=0 skip cmdtype '\ skips next instr if #1 '' outh #sd_cs '| /CS=1(disable) if reqd '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #check_DO ' '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< RET '/ else /CS=0 cmdRZA41/cmdRZtoken '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ READ REPLY: R1/R1+R3/R1+R7/R1+token + '+-----------------------------------------------------------------------------+ _getreply call #@_recvbyte ' recv R1 byte cmp reply, #$FF wz ' reply=$FF=busy ? if_nz jmp #.doneR1 ' n: ' timeout set in CMD0(for CMD0,8,55,A41,58,16) and CMD9,10,17(readblock) getct replyR1 '\ timeout ? cmpm timeout, replyR1 wc '| c if timeout < replyR1 if_nc jmp #@_getreply '| n: try again _RET_ MODCZ _set,_clr wcz '/ timeout C & NZ = fail '+=============================================================================+ .doneR1 mov replyR1, reply ' save R1/Token reply '+-----------------------------------------------------------------------------+ cmp cmdout, #CMD8 wz if_nz cmp cmdout, #CMD58 wz if_nz jmp #.end ' ret if not CMD8/CMD58 '+-----------------------------------------------------------------------------+ call #@_recvlong ' R7=CMD8=volts/R3=CMD58=OCR '+-----------------------------------------------------------------------------+ .end '\ returns with... '| nc+z replyR1=$00(success) test replyR1, #1 wz '| nc+nz replyR1=$01(idle) _RET_ cmpr replyR1, #$01 wc '/ c replyR1>$01(error) '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ SD SPI Send/Recv Routines... (write/read byte/long simultaneously) + '+ /CS=0 & CLK=0 on both entry and exit + '+-----------------------------------------------------------------------------+ _recvlong neg dataout, #1 ' call here to Recv a Long (+send 1's) _sendlong mov bitscnt, #32 ' call here to Send a Long (long=32bits) jmp #@_sendrecv ' _sendFF ' call here to Send $FF Byte _recvbyte neg dataout, #1 ' call here to Recv a Byte (+send 1's) _sendbyte rol dataout, #24 ' call here to Send a Byte (msbit first) mov bitscnt, #8 ' (byte=8bits) _sendrecv mov reply, #0 ' clear reply ' 8+15 low/high clk cycles (8.7MHz@200MHz, 1.3MHz@30MHz) .nextbit rol dataout, #1 wc ' \ prepare output bit (DI=0/1).. outl #sd_ck ' | CLK=0 (already 0 first time) outc #sd_di ' / write output bit: output on CLK falling edge waitx #2 ' | setup time to be safe outh #sd_ck ' \ CLK=1 waitx #3 ' | setup time to be safe testp #sd_do wc ' | read input bit: sample on CLK rising edge rcl reply, #1 ' / accum DO input bits djnz bitscnt, #.nextbit ' 8/32 bits? _RET_ outl #sd_ck ' CLK=0 on exit '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ /CS=1, Release SD Card DO pin, tristate SD CS/CK/DI/DO + '+-----------------------------------------------------------------------------+ _releaseDO outh #sd_cs ' /CS=1(disable) '''' call #@_sendFF ' 8 CLKs '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_releaseDO '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #check_DO '??????????????????? '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< andn dirb, ##($F<<26) ' tristate CS/CK/DI/DO ret wcz ' restore flags '+=============================================================================+ spare long 0 ' keep here to make monitor/debugger compile to same location as P2-ES ''=============================================================================================== '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< check_DO outh #sd_cs ' /CS->1 (disabled) mov dataout, lmm_p ' save lmm_p testp #sd_do wc ' test DO pin? if_nc mov lmm_p, ##str_DO_0 if_c mov lmm_p, ##str_DO_1 call #_hubTxString waitx #delay5us ' rep @.rep,#(8*2) ' outnot #sd_ck '\ CLK=0-->1-->0 waitx #delay5us '/ 5us @20MHz 100KHz (20MHz/100KHz/2-2=98) .rep ' /CS=1 & CLK=0 (idle) testp #sd_do wc ' test DO pin? if_nc mov lmm_p, ##str_0 if_c mov lmm_p, ##str_1 call #_hubTxString call #_hubTxCR mov lmm_p, dataout ' restore lmm_p RET wcz ''=============================================================================================== ''=============================================================================================== hubstring byte "P2-EVAL ROM_Booter_v33j_SD_003n",13,10,0 str_fail byte "SD boot failed",13,10,0 str_init byte "INIT:",13,10,0 str_cmd byte "(CMD: ",0 str_byte byte "w) byte mode",13,10,0 str_block byte "i) block mode",13,10,0 str_csd byte "CSD: ",0 str_cid byte "CID: ",0 str_mbr byte "MBR: ",0 str_vol byte "VOL: ",0 str_fsi byte "FSI: ",0 str_fat byte "FAT: ",0 str_dir byte "DIR: ",0 str_file byte "FILE: ",0 str_read byte "sector: ",0 str_load byte "LOADED:",13,10,0 str_run byte "RUN:",13,10,0 str_ser byte "All done!",13,10,0 str_ptn0 byte "i) ptn type $",0 str_fail_DO byte "SD-DO ***failed*** ",0 str_pass_DO byte "SD-DO tristate ",0 str_timeout byte "e) ***timeout***",13,10,0 str_exFAT byte "e) ***exFAT***",13,10,0 str_DO_0 byte "DO = 0 ",0 str_DO_1 byte "DO = 1 ",0 str_0 byte "0",0 str_1 byte "1*****",0 str_releaseDO byte "Release ",0 str_check byte "===checkpoint=== ",0 str_returned byte "Load/Run File returned ",0 ''=============================================================================================== alignl {{ '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_p, ##str_check '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_HubTxString '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_c mov lmm_x, ##$2043 ' "C " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nc mov lmm_x, ##$20434E ' "NC " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_z mov lmm_x, ##$205A ' "Z " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if_nz mov lmm_x, ##$205A4E ' "NZ " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, bufad '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, #" " '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTx '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mov lmm_x, reply '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubHex8 '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< call #_hubTxCR '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< }} '