📄 ide.s
字号:
;* to is passed in the param1 parameter, as defined in the header of this file.
;* The data byte to be written is passed in param2.
;*
;* The front of this routine has a chunk of bit manipulation code to translate the
;* param1 address bit allocation to the IDE pins on ports B & F.
;*
;* This routine does the following on the IDE bus: (all times are minimums)
;*
;* Write the 5-bit address (with read, write, reset all high)
;* Wait 50 ns
;* Set /WR low
;* Wait 290 ns
;* While waiting, set the low byte port to be an output
;* While waiting, write param2 to the low 8 bits of the IDE bus
;* Set /WR high
;* Wait 20 ns
;* Set the low byte port to be inputs
;* return
;*
;* Accepts: Address in param1, byte to write in param2
;* Returns: Nothing
;* Uses: temp, flags.
;*
;**********************************************************************************
IDE_write8:
; put A0-2 on port b, and cs0, cs1 on port f
in temp,PORTB
bst param1,3
bld temp,5 ; param1:3 -> temp:5 (A0)
bst param1,4
bld temp,6 ; param1:4 -> temp:6 (A1)
bst param1,5
bld temp,7 ; param1:5 -> temp:7 (A2)
out PORTB,temp ; write A0-2 onto the IDE bus
lds temp,PORTF
bst param1,6
bld temp,2 ; param1:6 -> temp:2 (/CS1)
bst param1,7
bld temp,3 ; param1:7 -> temp:3 (/CS0)
sts PORTF,temp ; write /CS0, /CS1 onto the IDE bus
; make /WR low
lds temp,PORTF
cbr temp,2 ; clear bit 1, the /WR line
sts PORTF,temp ; and write it to the IDE bus
out IDEDATAL,param2 ; write data byte onto IDE bus port
ldi temp,255
out IDEDATAL_DDR,temp ; low byte direction set for output
nop
nop
nop
nop ; finish waiting the 290 ns
; make /WR high
lds temp,PORTF
sbr temp,2 ; set bit 1, the /WR line
sts PORTF,temp ; and write it to the IDE bus
ldi temp,0
out IDEDATAL_DDR,temp ; low byte direction set for input
ret
;**********************************************************************************
;*
;* IDE_read16_C
;*
;* C-callable version of IDE_Read16 below.
;*
;* u16 IDE_read16_C (u08 idereg);
;*
;* Address of IDE register to read from is passed in via r24. Result is returned
;* via r25:r24
;*
;**********************************************************************************
IDE_read16_C:
push param1
push param2
mov param1,r24
rcall IDE_read16
mov r24,param1 ; low byte return
mov r25,param2 ; high byte return
pop param2
pop param1
ret
;**********************************************************************************
;*
;* IDE_read16
;* Read an 16 bit value from the IDE interface
;*
;* This routine reads a 16-bit word from the IDE interface. The 5 bit "address" to be read
;* from is passed in the param1 parameter, as defined in the header of this file.
;* The low byte read from the drive is returned in param1; the high byte in param2.
;*
;* The start of this routine contains a chunk of bit manipulation code to convert the
;* param1 address bit allocation into bit mappings for ports B & F.
;*
;* This routine does the following on the IDE bus: (all times are minimums)
;*
;* Write the 5-bit address (with read, write, reset all high)
;* Wait 50 ns
;* Set /RD low
;* Wait 125 ns
;* Read the 2 bytes (low and high) from the IDE bus
;* Set /RD high
;* return
;*
;* Accepts: Address in param1
;* Returns: Low byte read in param1; high byte in param2
;* Uses: flags.
;*
;**********************************************************************************
IDE_read16:
push temp
; Test code only - wait until BSY bit in status register is clear and RDY bit is set.
; push param1 ; preserve the original IDE address
IDE_read16_test:
; ldi param1,IDERD_ST
; rcall IDE_read8 ; read status register
; sbrc param1,IDEST_BSY_BIT ; skip forward if BSY bit clear
; rjmp IDE_read16_test3 ; repeat if BSY bit set (drive is busy)
; sbrs param1,IDEST_RDY_BIT ; skip forward if RDY bit set
; rjmp IDE_read16_test3 ; repeat if RDY bit clear (drive is not ready)
; sbrs param1,IDEST_COR_BIT
; rjmp IDE_read16_test2 ; jump forward if correctable error bit clear
; ldi param1,'Z'
; call UART_TxCharWait
; ldi param1,'C'
; call UART_TxCharWait
; ldi param1,'O'
; call UART_TxCharWait
; ldi param1,'R'
; call UART_TxCharWait ; print debug message if correctable error bit set
IDE_read16_test2:
; pop param1
; end of test code
; put A0-2 on port b, and cs0, cs1 on port f
in temp,PORTB
bst param1,3
bld temp,5 ; param1:3 -> temp:5 (A0)
bst param1,4
bld temp,6 ; param1:4 -> temp:6 (A1)
bst param1,5
bld temp,7 ; param1:5 -> temp:7 (A2)
out PORTB,temp ; write A0-2 onto the IDE bus
lds temp,PORTF
bst param1,6
bld temp,2 ; param1:6 -> temp:2 (/CS1)
bst param1,7
bld temp,3 ; param1:7 -> temp:3 (/CS0)
sts PORTF,temp ; write /CS0, /CS1 onto the IDE bus
; make /RD low
lds temp,PORTF
cbr temp,16 ; clear bit 4, the /RD line
sts PORTF,temp ; and write it to the IDE bus
nop
nop ; wait a bit (125 ns)
in param1,IDEDATAL_PIN ; read the low 8 bits of the IDE bus
in param2,IDEDATAH_PIN ; read the high 8 bits of the IDE bus
; make /RD high again
lds temp,PORTF
sbr temp,16 ; set bit 4, the /RD line
sts PORTF,temp ; and write it to the IDE bus
pop temp
ret
; test code - busy bit or ready could result in endless loop. So print debug info if busy bit set or ready bit clear
IDE_read16_test3:
call UART_PutHexWait ; print value of status register
ldi param1,' '
call UART_TxCharWait
ldi param1,'I'
call UART_TxCharWait
ldi param1,'D'
call UART_TxCharWait
ldi param1,'E'
call UART_TxCharWait
ldi param1,'r'
call UART_TxCharWait
ldi param1,'1'
call UART_TxCharWait
ldi param1,'6'
call UART_TxCharWait
ldi param1,'\r'
call UART_TxCharWait
ldi param1,'\n' ; followed by a short message
call UART_TxCharWait
rjmp IDE_read16_test ; then loop back to check busy bit again
; end of test code segment
;**********************************************************************************
;*
;* IDE_AutoPD
;* Enables automatic power-down on the drive
;*
;* This routine issues a command to the drive to enable automatic power-down
;* mode. This mode greatly reduces power consumption, heat dissipation, and noise
;* of the drive when it is not being accessed. It functions as follows:
;*
;* This routine does the following on the IDE bus: (all times are minimums)
;*
;* Wait for drive to not be busy (BSY=0 in status register)
;* Write a 13 to the SECTOR COUNT register
;* Wait for drive to set RDY
;* Write the command $E2 - Standby Mode, Automatic Power Down to the drive
;* return
;*
;*
;* Accepts: nothing
;* Returns: nothing
;* Uses: flags.
;* zeros r1
;*
;**********************************************************************************
IDE_AutoPD:
push temp
push param1
push param2
IDE_AutoPDAA:
; wait for drive to clear busy flag
ldi temp,IDERD_ST
mov param1,temp
rcall IDE_read8 ; read status register
sbrc param1,IDEST_BSY_BIT ; skip forward if BSY bit clear
rjmp IDE_AutoPDAA ; repeat if BSY bit set (drive is busy)
; make sure drive has ready (RDY) bit set
sbrs param1,IDEST_RDY_BIT ; skip forward if RDY bit set
rjmp IDE_AutoPDAA ; repeat if RDY bit clear (drive is not ready)
; write 13 to sector count register
ldi temp,IDEWR_SC
mov param1,temp ; sector count register address in param1
ldi temp,13
mov param2,temp ; 13 in param2
rcall IDE_write8 ; write 13 to SECTOR COUNT register
; wait for drive to set ready flag
IDEAPD: ldi temp,IDERD_ST
mov param1,temp
rcall IDE_read8 ; read status register
sbrs param1,IDEST_RDY_BIT ; skip forward if DRDY bit set
rjmp IDEAPD ; repeat if DRDY bit clear
; write command $E2 to the drive & return
ldi temp,IDEWR_CMD
mov param1,temp ; param1: command register address
ldi temp,0xe2
mov param2,temp ; param2: $e2
rcall IDE_write8 ; write command to drive
clr r1 ; zero r1 (for the C compiler)
pop param2
pop param1
pop temp
ret
;**********************************************************************************
;*
;* IDE_Standby
;* Tells the drive to immediately go into standby mode
;*
;* This routine does the following on the IDE bus: (all times are minimums)
;*
;* Wait for drive to not be busy (BSY=0 in status register)
;* Make sure drive is ready
;* Write the command $E0 - Standby Immediate, to the drive
;* return
;*
;*
;* Accepts: nothing
;* Returns: nothing
;* Uses: flags.
;* zeros r1
;*
;**********************************************************************************
IDE_Standby:
push temp
push param1
push param2
IDE_StandbyAA:
; wait for drive to clear busy flag
ldi temp,IDERD_ST
mov param1,temp
rcall IDE_read8 ; read status register
sbrc param1,IDEST_BSY_BIT ; skip forward if BSY bit clear
rjmp IDE_StandbyAA ; repeat if BSY bit set (drive is busy)
; make sure drive has ready (RDY) bit set
sbrs param1,IDEST_RDY_BIT ; skip forward if RDY bit set
rjmp IDE_StandbyAA ; repeat if RDY bit clear (drive is not ready)
; write command $E0 to the drive & return
ldi temp,IDEWR_CMD
mov param1,temp ; param1: command register address
ldi temp,0xe0
mov param2,temp ; param2: $e0
rcall IDE_write8 ; write command to drive
clr r1 ; zero r1 (for the C compiler)
pop param2
pop param1
pop temp
ret
;**********************************************************************************
;*
;* SeekSectorC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -