Well, as I like say, you can't argue with success
A bit of feedback:
- As you already set the drive_head register for drive 0 and the upper 4 LBA address bits as zero, you shouldn't have to set them again (my assumption below)
- As this is pointed to by the reset vector, the stack pointer is not set by default (perhaps it doesn't matter)
- You can save a byte using a loop to fill the rest of the LBA number in to the 3 registers
Here's what I copy/pasted from my BIOS, with some changes, that should load a block to memory. It's a bit different, is 76 bytes, but untested!
Code:
;
;Reset Vector points to here!
; Assume you have a working IDE controller ;-)
; Just set it up to load LBA zero to memory and jump to it.
; - this assumes the single 512-byte contains rest of the boot loader, which can be more flexible
;
; NOTE: constants and variable are not shown here!
; - you need to define the IDE registers, the BIOS_XFER pointer in page zero and the load address!
;
;Init the IDE controller
; First, set the stack pointer, then setup the IDE controller to read a block into memory
;
IDE_INIT
LDX #$FF ;Get $FF
TXS ;Set Stack pointer
;
JSR TST_IDE_BUSY ;Check/wait if IDE is still busy after HW Reset (6)
;
; Setup memory pointers first:
LDA #<LOAD_ADDR ;Get Load address
LDY #>LOAD_ADDR ; A/Y = Low/High
STA BIOS_XFERL ;Set Page Zero pointer
STY BIOS_XFERH ; Load/high
;
;IDE Setup
; First, set 8-bit mode, then setup for LBA zero to start loading from.
; - also set for a single block transfer (a partition record)
; - then send the read block command
;
LDX #$03 ;Set Index count for 3 (2)
PARM_XFER_LP
STZ IDE_SCT_NUM-1,X ;Zero IDE lower LBA registers (5)
DEX ;Decrement count (2)
BNE PARM_XFER_LP ;Loop back till done (2/3)
;
INX ;Increment X to $01
STX IDE_SCT_CNT ;Send to IDE for 1 block xfer (4)
;
STX IDE_FEATURE ;Send to IDE controller (4)
LDA #%11100000 ;Get Drive 0, LBA. mode, etc. (2)
STA IDE_DRV_HEAD ;Send to IDE controller (4)
LDA #$EF ;Get Set Features Command (2)
JSR SEND_IDE_CMD ;Send to IDE and wait till accepted
;
LDA #$20 ;Get LBA Read command
JSR SEND_IDE_CMD ;Send to IDE and wait till accepted
;
; - Check for Data Request (DRQ), as the Read LBA operation is the main function
; of the ISR, which will handle the data transfer from the IDE controller to store the
; data into memory. This ISR will handle single and multiple block transfers.
;
LBA_XFER LDA IDE_STATUS ;Get Status (clears IRQ) (4)
AND #%00001000 ;Check for DRQ (2)
BEQ IDE_RD_DONE ;If not active, done, exit (2/3)
;
IDE_RD_RBLK
LDA IDE_DATA ;Read a byte from IDE (4)
STA (BIOS_XFERL) ;Store low byte (5)
INC BIOS_XFERL ;Increment pointers (5)
BNE IDE_RD_RBLK ; (2/3)
INC BIOS_XFERH ; (5)
BRA LBA_XFER ;Loop back until done
;
IDE_RD_DONE
JMP (LOAD_ADDR) ;Jump to code to start
;
SEND_IDE_CMD
STA IDE_COMMAND ;Send command to IDE
;
TST_IDE_BUSY
;
;Test for IDE Controller Busy
; This routine loops on the Busy flag. If the IDE Controller is busy, no other
; status register flags are valid and no commands can be sent to the IDE Controller.
; Hence, this routine is key to determine if the IDE Controller is available to
; accept a command. Bit 7 is the Busy Bit. The 65C02 will set the "n" flag
; if Bit 7 is active, else clear it.
;
LDA IDE_ALT_STATUS ;Get IDE Alternate Status register (4)
BMI TST_IDE_BUSY ;Loop until BUSY bit is clear (2/3)
RTS ;Return to Caller (6)
;
If you ditch the stack setup, that saves 3 bytes, if you just zero the one page zero pointer, that saves 2 more bytes. Also, you would add 2 bytes by loading more than 1 block.
Hope this helps...