;***************************************************************************
;
; File Name:'cf.asm"
; Title:Compact Flash Common Memory Mode Driver
; Date:2004.05.12.
; Version:1.0.0
; Support telephone :+36-70-333-4034,old: +36-30-9541-658 VFX
; Support fax:
; Support Email:info@vfx.hu
; Target MCU:AVR
;
;***************************************************************************
; D E S C R I P T I O N
;
; Memory Interface to a compact flash card.
; Compact flash card is used in memory mapped mode.
; Registers are located at ADR_CFC in external RAM space of Mega128
;
;
;***************************************************************************
; M O D I F I C A T I O NH I S T O R Y
;
;
;rev.datewhowhy
; ---- -------------------------------------------------
; 0.01 2004.05.12VFXCreation
;
;***************************************************************************
;Hardware
;***************************************************************************
;*
;* SYSCLK: f=16.000 MHz (T= 62.5 ns)
;*
;***************************************************************************
;
;
;**************************************************************************
;* Hardware Def.
;
; CompactFlash hardware definitions
; Table 34: Memory Mapped Decoding
; -REG A10 A9-A4 A3 A2 A1 A0 Offset -OE=0-WE=0Notes
;10X00000Even RD DataEven WR Data1, 2
;10X00011ErrorFeatures1, 2
;10X00102Sector CountSector Count
;10X00113Sector No.Sector No.
;10X01004Cylinder LowCylinder Low
;10X01015Cylinder HighCylinder High
;10X01106Select Card/HeadSelect Card/Head
;10X01117StatusCommand
;10X10008Dup. Even RD DataDup. Even WR Data2
;10X10019Dup. Odd RD DataDup. Odd WR Data2
;10X1101DDup. Error Dup.Features2
;10X1110EAlt StatusDevice Ctl
;10X1111FDrive AddressReserved
;11XXXX08Even RD DataEven WR Data3
;11XXXX19Odd RD DataOdd WR Data3
;Note: 1) Register 0 is accessed with -CE1 low and -CE2 low as a word register
;on the combined Odd Data Bus and Even Data Bus (D15-D0). This register may
;also be accessed by a pair of byte accesses to the offset 0 with -CE1 low and
;-CE2 high. Note that the address space of this word register overlaps
;the address space of the Error and Feature byte-wide registers that lie at
;offset 1. When accessed twice as byte register with -CE1 low, the first byte
;to be accessed is the even byte of the word and the second byte accessed
;is the odd byte of the equivalent word access.
;A byte access to address 0 with -CE1 high and -CE2 low accesses the error
;(read) or feature (write) register.
;2) Registers at offset 8, 9 and D are non-overlapping duplicates of the
;registers at offset 0 and 1. Register 8 is equivalent to register 0,
;while register 9 accesses the odd byte. Therefore, if the registers are byte
;accessed in the order 9 then 8 the data will be transferred odd byte then even
;byte. Repeated byte accesses to register 8 or 0 will access consecutive
;(even then odd) bytes from the data buffer. Repeated word accesses to register
;8, 9 or 0 will access consecutive words from the data buffer. Repeated byte
;accesses to register 9 are not supported. However, repeated alternating byte
;accesses to registers 8 then 9 will access consecutive (even then odd) bytes
;from the data buffer. Byte accesses to register 9 access only the odd byte of
;the data.
;3) Accesses to even addresses between 400h and 7FFh access register 8.
;Accesses to odd addresses between 400h and 7FFh access register 9. This
;1 Kbyte memory window to the data register is provided so that hosts can
;perform memory to memory block moves to the data register when the register
;lies in memory space.
;
;
;CF register addresses
;
.equ CF_EvenData = ADR_CFC+0x08 ;Dupl. DAta
.equ CF_OddData = ADR_CFC+0x09 ;Dupl. Data
.equ CF_Error = ADR_CFC+0x0D ;Dupl. Errors / Features
.equ CF_SECCOUNT = ADR_CFC+0x02 ;Sectorcount
.equ CF_LBA0= ADR_CFC+0x03 ;LBA 0-7
.equ CF_LBA1= ADR_CFC+0x04 ;LBA 8-15
.equ CF_LBA2= ADR_CFC+0x05 ;LBA 16-23
.equ CF_LBA3= ADR_CFC+0x06 ;LBA 24-27
.equ CF_STACOM = ADR_CFC+0x07 ;Status / Command
.equ CF_DecCont = ADR_CFC+0x0E ;
;Class 1
;Upon receipt of a Class 1 command, the CompactFlash Storage Card sets BSY
;within 400 nsec.
;Class 2
;Upon receipt of a Class 2 command, the CompactFlash Storage Card sets BSY
;within 400 nsec, sets up the sector buffer for a write operation, sets DRQ
;within 700 usec, and clears BSY within 400 nsec of setting DRQ.
;Class 3
;Upon receipt of a Class 3 command, the CompactFlash Storage Card sets BSY
;within 400 nsec, sets up the sector buffer for a write operation, sets DRQ
;within 20 msec (assuming no re-assignments), and clears BSY within 400 nsec
;of setting DRQ.
;Table 37: CF-ATA Command Set
;
;Class COMMAND Code FR SC SN CY DH LBA
;1 Check Power Mode E5h or 98h - - - - D -
;1 Execute Drive Diagnostic 90h - - - - D -
;1 Erase Sector(s) C0h - Y Y Y Y Y
;1 Flush Cache E7h - - - - D -
;2 Format Track 50h - Y - Y Y Y
;1 Identify Drive ECh - - - - D -
;1 Idle E3h or 97h - Y - - D -
;1 Idle Immediate E1h or 95h - - - - D -
;1 Initialize Drive Parameters 91h - Y - - Y -
;1 Key Management Structure Read B9 Feature 0-127 C C C C D C -
;1 Key Management Read Keying Material B9 Feature 80 C C C C D C -
;2 Key Management Change Key Management Value B9 Feature 81 C C C C D C -
;1 NOP 00h - - - - D -
;1 Read Buffer E4h - - - - D -
;1 Read Long Sector 22h or 23h - - Y Y Y Y
;1 Read Multiple C4h - Y Y Y Y Y
;1 Read Sector(s) 20h or 21h - Y Y Y Y Y
;1 Read Verify Sector(s) 40h or 41h - Y Y Y Y Y
;1 Recalibrate 1Xh - - - - D -
;1 Request Sense 03h - - - - D -
;1 Security Disable Password F6h - - - - D -
;1 Security Erase Prepare F3h - - - - D -
;1 Security Erase Unit F4h - - - - D -
;1 Security Freeze Lock F5h - - - - D -
;1 Security Set Password F1h - - - - D -
;1 Security Unlock F2h - - - - D -
;1 Seek 7Xh - - Y Y Y Y
;1 Set Features EFh Y - - - D -
;1 Set Multiple Mode C6h - Y - - D -
;1 Set Sleep Mode E6h or 99h - - - - D -
;1 Standby E2h or 96h - - - - D -
;1 Standby Immediate E0h or 94h - - - - D -
;1 Translate Sector 87h - Y Y Y Y Y
;1 Wear Level F5h - - - - Y -
;2 Write Buffer E8h - - - - D -
;2 Write Long Sector 32h or 33h - - Y Y Y Y
;3 Write Multiple C5h - Y Y Y Y Y
;3 Write Multiple w/o Erase CDh - Y Y Y Y Y
;2 Write Sector(s) 30h or 31h - Y Y Y Y Y
;2 Write Sector(s) w/o Erase 38h - Y Y Y Y Y
;3 Write Verify 3Ch - Y Y Y Y Y
;
;Definitions:
;FR = Features Register
;SC = Sector Count Register
;SN = Sector Number Register
;CY = Cylinder Registers
;DH = Card/Drive/Head Register
;LBA = Logical Block Address Mode Supported (see command descriptions for use).
;Y - The register contains a valid parameter for this command. For the Drive/Head Register Y
;means both the CompactFlash Storage Card and head parameters are used; D - only the
;CompactFlash Storage Card parameter is valid and not the head parameter; C - The register
;contains command specific data (see command descriptions for use).
;
;CF-ATA Command Set
.equ CF_CMD_READ_SEC= 0x20
.equ CF_CMD_WRITE_SEC = 0x30
.equ CF_CMD_IDENTIFY= 0xEC
.equ CFRDY = 2;bit 2 = 1 CF ready
.equ CFVS1 = 3;bit 3 = 0 CF in slot
;***************************************************************************************
;*** Definition of the status register bits
;***
;*** Bit7Bit0
;*** BSYDRDYDWFDSCDRQCORRIDXERR
;***************************************************************************************
.equ CFC_STATUS_BSY = 0x80;Busy flag
.equ CFC_STATUS_DRDY = 0x40;Drive ready
.equ CFC_STATUS_DWF = 0x20;Drive write fault
.equ CFC_STATUS_DSC = 0x10;Drive seek complete
.equ CFC_STATUS_DRQ = 0x08;Data request
.equ CFC_STATUS_CORR = 0x04;Corrected data
.equ CFC_STATUS_IDX = 0x02;Index
.equ CFC_STATUS_ERR = 0x01;Error
;
;***************************************************************************
;**** VARIABLES
.DSEG
;***************************************************************************
.ESEG
;***************************************************************************
;**** CODE SEG
;***************************************************************************
.CSEG
;********************************************************
;CFRdy
;
; Wait until CF not busy
;
; Out: c= 0 no error
;1 error
;
; Alt: R16,R17
;
CFHWRdy:
lds R16,ADR_CFST
bst R16,CFVS1;CF inserted?
brtc CFHWRdy0
rjmp CFDrvError
CFHWRdy0:
lds R16,ADR_CFST
bst R16,CFRDY;CF ready?
brtc CFHWRdy
clc
ret
;********************************************************
;CFWaitDRQ
;
; Wait until Data will available
;
; Out: c= 0 no error
;1 error
;
; Alt: R16,R17
;
CFWaitDRQ:
rcall CFHWRdy
brcc CFWaitDRQ00
ret
CFWaitDRQ00:
lds R16,CF_STACOM
bst R16,0
brtc CFWaitDRQ0
CFWaitErr:
ldi R16,low(0xFFF0);Error in last command
ldi R17,high(0xFFF0) ;ide keresunk egy error kodot!!!
sec
ret
CFWaitDRQ0:
andi R16,0xF8
cpi R16,0x58
brne CFWaitDRQ
clc
ret
;********************************************************
;CFWaitReady
;
; Wait until CF will ready
;
; Out: c= 0 no error
;1 error
;
; Alt: R16,R17
;
CFWaitReady:
rcall CFHWRdy
brcc CFWaitRdy0
ret
CFWaitRdy0:
lds R16,CF_STACOM
bst R16,0
brts CFWaitErr
CFWaitReady01:
andi R16,0xF0
cpi R16,0x50
brne CFWaitReady
clc
ret
;********************************************************
;CFReadSector
;
; In: R13:R12:R11:R10 - LBA sector number
;Page: Y - Pointer to Data Buffer[512 byte]
;Z - Phis. Drive Descriptor
;
; Out: c= 0 no error
;1 error
;
CFReadSector:
ldd R0,Z+MaxSector+0
ldd R1,Z+MaxSector+1
ldd R2,Z+MaxSector+2
ldd R3,Z+MaxSector+3
cp R10,R0
cpc R11,R1
cpc R12,R2
cpc R13,R3
brcs CFReadSec00
ldi R16,low(ERROR_SECTOR_NOT_FOUND) ;Sector number too big
ldi R17,high(ERROR_SECTOR_NOT_FOUND)
sec
ret
CFReadSec00:
std Z+CurrentSector+0,R10
std Z+CurrentSector+1,R11
std Z+CurrentSector+2,R12
std Z+CurrentSector+3,R13
rcall CFWaitReady
brcc CFReadSec01
ret;Error in last command
CFReadSec01:
ldi R16,1
sts CF_SECCOUNT,R16
nop
sts CF_LBA0,R10;D7..D0
nop
sts CF_LBA1,R11;D15..D8
nop
sts CF_LBA2,R12;D23..D16
ldi R16,0x0F
and R16,R13
ori R16,0xE0;set LBA mode
sts CF_LBA3,R16;D27..D24 + LBA mode + Drive0
ldi R16,CF_CMD_READ_SEC
sts CF_STACOM,R16;Set Read Sector Command
ldi XL,0
ldi XH,1;if X==0 -> X=256 word;
movw R0,YL;save Y reg.
rcall CFWaitDrq
brcc CFReadSec02
ret;Drive error
CFReadSec02:
lds R16,ADR_CFST
bst R16,CFVS1;CF inserted?
brts CFDrvError
bst R16,CFRDY;CF ready?
brtc CFReadSec02
lds R16,CF_EvenData
st Y+,R16
lds R16,CF_OddData
st Y+,R16
sbiw XL,1
brne CFReadSec02
movw YL,R0;restore Y reg.
clc
ret
CFDrvError:
ldi R16,low(ERROR_BAD_UNIT)
ldi R17,high(ERROR_BAD_UNIT) ;Drive not present
sec
ret
;********************************************************
;CFWriteSector
;
; In: R13:R12:R11:R10 - LBA sector number
;Page: Y - Pointer to Data Buffer[512 byte]
;Z - Phis. Drive Descriptor
;
; Out: c= 0 no error
;1 error
;
CFWriteSector:
ldd R0,Z+MaxSector+0
ldd R1,Z+MaxSector+1
ldd R2,Z+MaxSector+2
ldd R3,Z+MaxSector+3
cp R10,R0
cpc R11,R1
cpc R12,R2
cpc R13,R3
brcs CFWriteSec00
ldi R16,low(ERROR_SECTOR_NOT_FOUND) ;Sector number too big
ldi R17,high(ERROR_SECTOR_NOT_FOUND)
sec
ret
CFWriteSec00:
rcall CFWaitReady
brcc CFWriteSec01
ret;Error in last command
CFWriteSec01:
ldi R16,1
sts CF_SECCOUNT,R16
nop
sts CF_LBA0,R10;D7..D0
nop
sts CF_LBA1,R11;D15..D8
nop
sts CF_LBA2,R12;D23..D16
ldi R16,0x0F
and R16,R13
ori R16,0xE0;set LBA mode
sts CF_LBA3,R16;D27..D24 + LBA mode + Drive0
ldi R16,CF_CMD_WRITE_SEC
sts CF_STACOM,R16;Write sector command
ldi XL,0
ldi XH,1;if X==0 -> X=256 word;
movw R0,YL
rcall CFWaitDrq
brcc CFWriteSec02
ret;Drive error
CFWriteSec02:
lds R16,ADR_CFST
bst R16,CFVS1;CF inserted?
brts CFDrvError
bst R16,CFRDY;CF ready?
brtc CFWriteSec02
ld R16,Y+
sts CF_EvenData,R16
ld R16,Y+
sts CF_OddData,R16
sbiw XL,1
brne CFWriteSec02
movw YL,R0
clc
ret
;********************************************************
;CFResetDevice
;
; In: -
;
; Out: c= 0 no error
;1 error R17:R16 error code
;
CFResetDevice:
ldi R16,0b00000100;Force SW reset
sts ADR_CFC+0x0E,R16 ;Device Control Register
ldi R16,64
CFRes0:dec R17
brne CFRes0
dec R16
brne CFRes0
clr R16
sts ADR_CFC+0x0E,R16 ;Device Control Register
rcall CFWaitReady
ret
;********************************************************
;CFIdentify
;
; In: Z - Phis. Drive Descriptor
;Page: Y - Pointer to temporary Data Buffer [512 byte]
;
; Out: c= 0 no error
;1 error
;
CFIdentify:
rcall CFWaitReady
brcc CFIdent01
ret;Error code in R17:R16
CFIdent01:
ldi R16,1
sts CF_SECCOUNT,R16
clr R16
sts CF_LBA0,R16
nop
sts CF_LBA1,R16
nop
sts CF_LBA2,R16
ldi R16,0xE0
sts CF_LBA3,R16
ldi R16,CF_CMD_IDENTIFY
sts CF_STACOM,R16
ldi XL,0;read fixed 256 word
ldi XH,1
movw R0,YL
call CFWaitDRQ
brcc CFIdent02
ret;Drive error
CFIdent02:
lds R16,CF_EvenData
st Y+,R16
nop
lds R16,CF_OddData
st Y+,R16
sbiw XL,1
brne CFIdent02
movw YL,R0
clr R0
ldd R16,Y+0;CF IDs: 848Ah
cpi R16,0x8A
brne CFIDs0
ldd R16,Y+1
cpi R16,0x84
brneCFIDs0
inc R0
CFIDs0:
std Z+MediaFlag,R0;Store CF ID
ldi R16,RemovableMedia
std Z+MediaType,R16
ldi R16,0x80
std Z+DiskNumber,R16 ;First HDD => HDD0
ldd R16,Y+2;Default tracks/cylinders
ldd R17,Y+3
std Z+Cylinders+0,R16
std Z+Cylinders+1,R17
ldd R16,Y+6;Default Heads
std Z+Heads,R16
ldd R16,Y+12;default Sectors per track
std Z+SectorsPerTrack,R16
ldd R16,Y+14;Number of Sectors per Card
std Z+MaxSector+2,R16 ;MSW -LSW !!!
ldd R16,Y+15
std Z+MaxSector+3,R16
ldd R16,Y+16
std Z+MaxSector+0,R16
ldd R16,Y+17
std Z+MaxSector+1,R16
clc
ret