📄 ata.asm
字号:
/* ***********************************************************************
**
** Copyright (C) 2002 Jesper Hansen <jesperh@telia.com> and
** Romuald Bialy (MIS) <romek_b@o2.pl>.
**
**
** Yampp-3/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-01 1.0 MIS initial public release
** 2003-04-10 1.1 MIS code size optimisation
** 2003-05-06 1.1 MIS little code speed-up
**
*********************************************************************** */
#if((__GNUC__ * 1000 + __GNUC_MINOR__) != 3003)
#error ___ Wrong compiler version ! Use GCC 3.3 ___
#endif
#define __ASSEMBLER__ 1
#define __SFR_OFFSET 0
#include <avr/io.h>
//#include <io-avr.h>
#define ATA_ASM
#include "ata.h"
#define __tmp_reg__ r0
#define __zero_reg__ r1
;#define SLOW_DISK
.section .text
.extern delay10
.extern ramdisable
.extern ramenable
;*******************************************************************************
;*
;* ATA Interface stuff
;*
;*******************************************************************************
; 512 byte sector buffer in internal RAM
.comm ata_sbuf,512
.comm ata_drive,1
.comm ata_cmd,1
.comm ata_fun,1
.comm ata_stat,1
; r24
;void setaddress(u08 reg);
.global setaddress
setaddress:
call ramdisable ; disable RAM
ser r25
; make sure PORTA and C is outputs
out DDRA,r25
out DDRC,r25
out PORTA,r24
; out PORTC,__zero_reg__
; flip ALE
sbi PORTE,PE1
cbi PORTE,PE1
ret
; r24
;u08 ReadBYTE(u08 reg);
.global ReadBYTE
ReadBYTE:
rcall setaddress ; setup address on latch
out DDRA, __zero_reg__ ; outp(0x00, DDRA); // port A as input
out DDRC, __zero_reg__ ; outp(0x00, DDRC); // port C as input
ser r25
out PORTA,r25 ; activate pullup on port A
; nop
cbi PORTB,DIOR ; set DIOR lo
nop ; delay
#ifdef SLOW_DISK
nop
#endif
in r24,PINA ; read byte from PORTA
sbi PORTB,DIOR ; set DIOR hi
jmp ramenable
; call ramenable ; enable RAM
; clr r25
; ret
; r24 r22
;void WriteBYTE(u08 reg, u08 dat)
.global WriteBYTE
WriteBYTE:
rcall setaddress ; setup address on latch
out PORTA,r22 ; write byte to PORTA
out PORTC,__zero_reg__
; nop
cbi PORTB,DIOW ; set DIOW lo
#ifdef SLOW_DISK
nop
#endif
nop
sbi PORTB,DIOW ; set DIOW hi
jmp ramenable
; call ramenable ; enable RAM
; 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 r20 r19/r18
;u08 ATA_Read( u32 lba, u08 numsectors, u08*Buffer )
ATA_Read:
sts ata_stat,__zero_reg__ ; clear error flag
ldi r21,0x20 ; read command
rcall ATA_Request
tst r24
brne ATA_CMD_END
ATA_ReadBuffer:
rcall DiskToBuffer
ldi r27,hi8(ata_sbuf)
ldi r26,lo8(ata_sbuf) ; X points to buffer
movw r30,r18 ; Z points to RAM
rcall bufcopy ; copy X to Z
movw r18,r30 ; store back
dec r20
brne ATA_ReadBuffer
ATA_CMD_END: lds r24,ata_stat ; read ata error flag
mov r25,r24
ret
.global ATA_Write
; r25..r22 r20 r19/r18
;u08 ATA_Write( u32 lba, u08 numsectors, u08*Buffer )
ATA_Write:
sts ata_stat,__zero_reg__ ; clear error flag
ldi r21,0x30 ; write command
rcall ATA_Request
tst r24
brne ATA_CMD_END
.AW0:
ldi r31,hi8(ata_sbuf)
ldi r30,lo8(ata_sbuf) ; Z points to buffer
movw r26,r18 ; X points to RAM
rcall bufcopy ; copy X to Z
movw r18,r26 ; store back
; store to disk
rcall BufferToDisk
dec r20 ; dec sector counter
brne .AW0 ; and loop until done
rjmp ATA_CMD_END
#define USB_PORT PORTD
#define USB_TXRDY PD4
#define USB_RXRDY PD5
#define USB_WR PD6
#define USB_RD PD7
#define USB_ADDR 0x8000
.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 r21,0x20 ; read command
rcall ATA_Request
tst r24
brne ATA_CMD_END
.RTU0:
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 r21 ; loop count = 256 words
.RTU1:
sbic USB_PORT-2,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_PORT-2,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 r21 ; dec loop counter
brne .RTU1 ; and loop until done
dec r20 ; 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 r21,0x30 ; write command
rcall ATA_Request
tst r24
brne ATA_CMD_END
.LJ0:
; read from USB
ldi r31,hi8(ata_sbuf)
ldi r30,lo8(ata_sbuf) ; Z points to buffer
ldi r27,hi8(USB_ADDR)
ldi r26,lo8(USB_ADDR) ; X points to USB
clr r21 ; loop count = 256 words
.LJ1:
sbic USB_PORT-2,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 RAM
.LJ2:
sbic USB_PORT-2,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 RAM
dec r21 ; dec loop counter
brne .LJ1 ; and loop until done
; store to disk
rcall BufferToDisk
dec r20 ; dec sector counter
brne .LJ0 ; and loop until done
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;
; Command in R21
; r25..r22 r20
;u08 ATA_Request_Sectors_LBA( u32 lba, u08 numsectors);
.global ATA_Request
ATA_Request:
push r18 ; save buffer address
push r19
mov r19,r22 ; save sector (low LBA) value
mov r18,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,r18 ; get saved value
ldi r24,lo8(ATAPI_CountMSB) ; MSB of track (LBA 23:16)
rcall WriteBYTE
mov r22,r21
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
pop r19 ; restore buffer address
pop r18
rjmp ATA_WaitReady ; check and return result
;
; r21, r24,r25, r30,r31 modified
;
BufferToDisk:
rcall ATA_WaitBusy ; check disk ready for sector writing
; disable the RAM interface and SetAddress to point to Data Register
ldi r24,lo8(ATAPI_Data)
rcall setaddress
; set Z to ram buffer
ldi r31,hi8(ata_sbuf)
ldi r30,lo8(ata_sbuf)
clr r21 ; loop count = 256 words
BTD2:
ld r25,Z+ ; read from buffer
ld r24,Z+ ; read from buffer
out PORTA,r25 ; setup on PORTA
out PORTC,r24 ; setup on PORTC
#ifdef SLOW_DISK
nop
#endif
nop
cbi PORTB, DIOW ; set DIOW lo
; nop
sbi PORTB, DIOW ; set DIOW hi
dec r21 ; dec loop counter
brne BTD2 ; and loop until done
jmp ramenable
; call ramenable ; enable the RAM interface
; ret
;
; r21, r24,r25, r30,r31 modified
;
DiskToBuffer:
rcall ATA_WaitBusy ; check disk ready for sector reading
; disable the RAM interface and SetAddress to point to Data Register
ldi r24,lo8(ATAPI_Data)
rcall setaddress
; set Z to ram buffer
ldi r31,hi8(ata_sbuf)
ldi r30,lo8(ata_sbuf)
; set PORTA and PORTC as inputs
out DDRA,__zero_reg__ ; port A as input
out DDRC,__zero_reg__ ; port C as input
ser r25
out PORTA,r25 ; activate pullup on PORTA
out PORTC,r25 ; activate pullup on PORTC
clr r21 ; loop count = 256 words
DTB2:
cbi PORTB, DIOR ; set DIOR lo
#ifdef SLOW_DISK
nop
#endif
nop
in r24,PINA ; read lo byte
in r25,PINC ; read hi byte
sbi PORTB, DIOR ; set DIOR hi
st Z+,r24 ; write to buffer
st Z+,r25 ; write to buffer
dec r21 ; dec loop counter
brne DTB2 ; and loop until done
; enable the RAM interface
jmp ramenable
; call ramenable
; ret
;
; copy a sector from X to Z
;
bufcopy:
clr r21 ; loop count = 256 words
bc1:
ld r24,X+
st Z+,r24
ld r24,X+
st Z+,r24
dec r21 ; dec loop counter
brne bc1 ; and loop until done
ret
; r25/r24
;u08 IdentifyDrive(u08 *Buffer)
.global IdentifyDrive
IdentifyDrive:
sts ata_stat,__zero_reg__
push r24
push r25
clr r25
clr r24
movw r22,r24
clr r20
ldi r21,0xEC
rcall ATA_Request
pop r19
pop r18
ldi r20,1
rcall ATA_ReadBuffer
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -