📄 ata.asm
字号:
/* ***********************************************************************
**
** Copyright (C) 2002 Jesper Hansen <jesperh@telia.com> and
** Romuald Bialy (MIS) <romek_b@o2.pl>.
**
**
** Yampp-7/USB - low level support library
**
**
*************************************************************************
**
** This file is part of the yampp system.
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation,
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*************************************************************************
**
** Revision History
**
** when what who why
**
** 2002-09-22 1.0 MIS initial public release
** 2003-07-14 1.1 MIS added watchdog resets to USB<->CARD functions
** 2004-01-10 1.2 MIS fixed ATA_SetDrive function to avoid lockup if no card is present
**
*********************************************************************** */
#define __ASSEMBLER__ 1
#define __SFR_OFFSET 0
#include <avr/io.h>
#define ATA_ASM
#include "ata.h"
#define __tmp_reg__ r0
#define __zero_reg__ r1
#define USB_PIN PIND
#define USB_TXRDY PD3
#define USB_RXRDY PD2
#define USB_ADDR 0x8000
.section .text
;*******************************************************************************
;*
;* ATA Interface stuff
;*
;*******************************************************************************
; 512 byte sector buffer in internal RAM
.global ata_sbuf
.comm ata_sbuf,512
.comm ata_drive,1
.comm ata_stat,1
; r24
;u08 ReadBYTE(u08 reg);
.global ReadBYTE
ReadBYTE:
push r31 ; save register
mov r31,r24 ; only high 8 bytes are needed
ld r24,Z ; read byte
pop r31 ; restore
clr r25 ; clear high
ret
; r24 r22
;void WriteBYTE(u08 reg, u08 dat)
.global WriteBYTE
WriteBYTE:
push r31 ; save register
mov r31,r24 ; only high 8 bytes are needed
st Z,r22 ; write byte
pop r31 ; restore
ret
;
; r20,r24, X, Z modified
;
BufferToDisk:
; set Z to disk
ldi r31,lo8(ATAPI_RepData)
clr r30
; set X to ram buffer
ldi r27,hi8(ata_sbuf)
ldi r26,lo8(ata_sbuf)
clr r20 ; loop count = 256 words
btd1:
ld r24,X+
st Z,r24
ld r24,X+
st Z,r24
dec r20 ; dec loop counter
brne btd1 ; and loop until done
ret
;
; r20,r24, X, Z modified
;
DiskToBuffer:
; set X to disk
ldi r27,lo8(ATAPI_RepData)
clr r26
; set Z to ram buffer
ldi r31,hi8(ata_sbuf)
ldi r30,lo8(ata_sbuf)
clr r20 ; loop count = 256 words
dtb1:
ld r24,X
st Z+,r24
ld r24,X
st Z+,r24
dec r20 ; dec loop counter
brne dtb1 ; and loop until done
ret
;
; read status register
;
;
; r24,r25,r30,r31 destroyed
;
.global ATA_ReadStat
ATA_ReadStat:
ldi r24,lo8(ATAPI_Stat)
rjmp ReadBYTE
;
; r24,r25,r30,r31 destroyed
;
.global ATA_WaitBusy
ATA_WaitBusy:
rcall ATA_ReadStat ; read status register
tst r24 ; check for BUSY set
brlt ATA_WaitBusy ; set, goto check again
ret
;u08 WaitReady(void);
;
;modifies R24, R25, Z
;
.global ATA_WaitReady
ATA_WaitReady:
rcall ATA_WaitBusy ; get status register
sbrc r24,0 ; skip if Error bit is clear
rjmp ATA_wrdy2 ; else return err
sbrs r24,3 ; test for DRQ, skip if set
rjmp ATA_WaitReady ; not yet, loop again
ATA_wrdy2:
andi r24,1 ; return 0 on OK, 1 on FAIL
sts ata_stat,r24 ; save result
ret
; r24
;void ATA_SetDrive(u08 Drive);
.global ATA_SetDrive
ATA_SetDrive:
andi r24,1 ; mask bit
swap r24
ldi r25,0xE0 ; LBA and fixed bits for Device/Head register
or r24,r25 ; combine
sts ata_drive,r24 ; save in variable
mov r22,r24
ldi r24,lo8(ATAPI_DRVSelect)
; cli
rcall WriteBYTE ; write drive select value to drive
; rcall ATA_WaitBusy ; wait for not busy
; sei
ret
.global ATA_Read
; r25..r22
;u08 ATA_Read( u32 lba )
ATA_Read:
sts ata_stat,__zero_reg__ ; clear error flag
ldi r18,0x20 ; read command
ldi r20,1 ; request one sector
rcall ATA_Request
tst r24
brne ATA_CMD_END
rcall DiskToBuffer
ATA_CMD_END: lds r24,ata_stat ; read ata error flag
mov r25,r24
ret
.global ATA_Write
; r25..r22
;u08 ATA_Write( u32 lba )
ATA_Write:
sts ata_stat,__zero_reg__ ; clear error flag
ldi r18,0x30 ; write command
ldi r20,1 ; request one sector
rcall ATA_Request
tst r24
brne ATA_CMD_END
rcall BufferToDisk
rjmp ATA_CMD_END
.global ATA_Read_USB
; r25..r22 r20
;u08 ATA_Read_USB( u32 lba, u08 numsectors);
;
ATA_Read_USB:
sts ata_stat,__zero_reg__ ; clear error flag
ldi r18,0x20 ; read command
rcall ATA_Request
tst r24
brne ATA_CMD_END
mov r22,r20 ; save count
.RTU0:
wdr
rcall ATA_WaitReady
rcall DiskToBuffer
; send buffer to USB
ldi r27,hi8(ata_sbuf)
ldi r26,lo8(ata_sbuf) ; X points to buffer
ldi r31,hi8(USB_ADDR)
ldi r30,lo8(USB_ADDR) ; Z points to USB
clr r20 ; loop count = 256 words
.RTU1:
sbic USB_PIN,USB_TXRDY ; while flag is set
rjmp .RTU1 ; wait for bit to be cleared
ld r24,X+ ; read from RAM
st Z,r24 ; store to USB
.RTU2:
sbic USB_PIN,USB_TXRDY ; while flag is set
rjmp .RTU2 ; wait for bit to be cleared
ld r24,X+ ; read from USB
st Z,r24 ; store to RAM
dec r20 ; dec loop counter
brne .RTU1 ; and loop until done
dec r22 ; dec sector counter
brne .RTU0 ; and loop until done
rjmp ATA_CMD_END
; r25..r22 r20
;u08 ATA_Write_USB( u32 lba, u08 numsectors);
;
.global ATA_Write_USB
ATA_Write_USB:
sts ata_stat,__zero_reg__ ; clear error flag
ldi r18,0x30 ; write command
rcall ATA_Request
tst r24
brne ATA_CMD_END
cli
mov r22,r20 ; save count
.LJ0:
rcall ATA_WaitReady
wdr
ldi r31,lo8(ATAPI_RepData) ; Z points to CF card data register
clr r30
ldi r27,hi8(USB_ADDR)
ldi r26,lo8(USB_ADDR) ; X points to USB
clr r20 ; loop count = 256 words
.LJ1:
sbic USB_PIN,USB_RXRDY ; while flag is set
rjmp .LJ1 ; wait for bit to be cleared
ld r24,X ; read from USB
st Z,r24 ; store to CARD
.LJ2:
sbic USB_PIN,USB_RXRDY ; while flag is set
rjmp .LJ2 ; wait for bit to be cleared
ld r24,X ; read from USB
st Z,r24 ; store to CARD
dec r20 ; dec loop counter
brne .LJ1 ; and loop until done
dec r22 ; dec sector counter
brne .LJ0 ; and loop until done
sei
rjmp ATA_CMD_END
;****************************************
; head cyl sect
; 8 16 8
;r22 sect = (u16) ( lba & 0x000000ffL );
; lba = lba >> 8;
;r24/r23 cyl = (u16) ( lba & 0x0000ffff );
; lba = lba >> 16;
;r25 head = ( (u16) ( lba & 0x0fL ) ) | 0x40;
; r25..r22 r20 r18
;u08 ATA_Request_Sectors_LBA( u32 lba, u08 numsectors, u08 command);
.global ATA_Request
ATA_Request:
mov r19,r22 ; save sector (low LBA) value
mov r21,r24 ; save LBA 23:16
andi r25,0x0f ; mask high LBA (LBA 27:24)
lds r22,ata_drive ; get drive
or r22,r25 ; combine
rcall ATA_WaitBusy
ldi r24,lo8(ATAPI_DRVSelect)
rcall WriteBYTE ; write drive select value
; wait for !BUSY and DRDY
.L927:
rcall ATA_WaitBusy
sbrs r24,6 ; skip if DRDY is set
rjmp .L927
mov r22,r20
ldi r24,lo8(ATA_SectorCount) ; nSectors
rcall WriteBYTE
mov r22,r19 ; get saved value
ldi r24,lo8(ATA_Sector) ; Start Sector (LBA 7:0)
rcall WriteBYTE
mov r22,r23
ldi r24,lo8(ATAPI_CountLSB) ; LSB of track (LBA 15:8)
rcall WriteBYTE
mov r22,r21 ; get saved value
ldi r24,lo8(ATAPI_CountMSB) ; MSB of track (LBA 23:16)
rcall WriteBYTE
mov r22,r18
ldi r24,lo8(ATAPI_Cmd) ; Send the command
rcall WriteBYTE
nop
nop
nop
nop
; dummy read of Alternate Status register
ldi r24,lo8(ATAPI_AltStat)
rcall ReadBYTE
rjmp ATA_WaitReady ; check and return result
;
;u08 ATA_Identify(void)
.global ATA_Identify
ATA_Identify:
clr r25
clr r24
movw r22,r24
movw r20,r24
ldi r18,0xEC
rcall ATA_Request
tst r24
brne id_err
rcall DiskToBuffer
id_err: lds r24,ata_stat ; read ata error flag
clr r25
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -