⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide.asm

📁 6502bios,关于6502的sbc,有lcd,time,irq,模块
💻 ASM
字号:
; IDE functions
; Chris Ward, 24/12/1999

_IDE	;remember start address for code

	ORG IDE
;IDE registers, with equivalent PC I/O addresses listed
IDEDATA	.ds 1		;1F0: Data Port
IDEERR	.ds 1		;1F1: Error Register (read)
IDEPRE	EQU IDEERR	;1F1: Write Precompensation (write)
IDESECC	.ds 1		;1F2: Sector Count
IDESECT	.ds 1		;1F3: Sector Number
IDECYLL	.ds 1		;1F4: Cylinder Low
IDECYLH	.ds 1		;1F5: Cylinder High
IDEDRHD	.ds 1		;1F6: Drive / Head
IDESTS	.ds 1		;1F7: Status (read)
IDECMD	EQU IDESTS	;1F7: Command (write)

	ORG *+6		;3F0 - 3F5: unused
IDEASTS	.ds 1		;3F6: Alternate Status (read)
IDECTL	EQU IDEASTS	;3F6: Device Control (write)
IDEDADD	.ds 1		;3F7: Drive Address (read)

IDEHIGH	.ds 1		;latch for high 8 bits

	ORG _IDE
; *** Initialise IDE bus
; A,X,Y preserved
IDEINIT	PHA
	JSR IDEDRDY
	LDA #$A0
	STA IDEDRHD	;select drive 0, head 0
	LDA #$10
	STA IDECMD	;send recalibrate command
	JSR IDEBUSY
	PLA
	RTS

; *** Convert LBA address to CHS (Cylinder/Head/Sector) values
; input: LBA address at ZP locations IDELBA0,IDELBA1,IDELBA2,IDELBA3
;        Sectors per cylinder (HxS) at ZP location IDESPC
;        Sectors per track (S) at ZP location IDESPT
; output: CHS values loaded into IDE registers
; Y preserved
	;cylinder = LBA / SPC
LBA2CHS	LDA IDELBA0
	STA ZTMP0
	LDA IDELBA1
	STA ZTMP1
	LDA IDELBA2
	STA ZTMP2
	LDA IDELBA3
	STA ZTMP3
	LDA IDESPC
	STA ZTMP4
	LDA IDESPC+1
	STA ZTMP5
	LDA #0
	STA ZTMP6
	STA ZTMP7
	JSR UDIV32	;do the division
	LDA ZTMP0		;cylinder low byte
	STA IDECYLL
	LDA ZTMP1		;cylinder high byte
	STA IDECYLH

	;head = (LBA % SPC) / SPT
	;sector = (LBA % SPT) + 1
	;will do division by repeated subtraction
	LDX #0
LBA2CH0	SEC
	LDA ZTMP8
	SBC IDESPT	;subtract low byte
	BCS LBA2CH1
	DEC ZTMP9		;carry=0 -> borrow from high byte
	BCC LBA2CH2	;high byte rollover -> finished
LBA2CH1	STA ZTMP8
	INX
	JMP LBA2CH0

	;we now have X=head, A=sector-1
LBA2CH2	ADC IDESPT
	CLC
	ADC #1
	STA IDESECT	;write to sector register
	TXA
	ORA #$A0		;set LBA=0, DEV=0
	STA IDEDRHD	;write to drive/head register
	RTS

; *** Test the LBA2CHS routine with data sent from PC on serial port
LBATEST	JSR RXBYTE
	STA IDESPC
	JSR RXBYTE
	STA IDESPC+1
	JSR RXBYTE
	STA IDESPT
	JSR RXBYTE
	STA IDELBA0
	JSR RXBYTE
	STA IDELBA1
	JSR RXBYTE
	STA IDELBA2
	JSR RXBYTE
	STA IDELBA3
	JSR LBA2CHS
	LDA IDECYLL
	JSR TXBYTE
	LDA IDECYLH
	JSR TXBYTE
	LDA IDEDRHD
	AND #$0F
	JSR TXBYTE
	LDA IDESECT
	JSR TXBYTE
	JMP LBATEST

; *** Wait until drive is not busy
; A,X,Y preserved
IDEBUSY	PHA
IDEBUSY0	LDA IDESTS	;read status register
	AND #$80		;select bit 7 (BUSY)
	BNE IDEBUSY0	;loop if set
	PLA
	RTS

; *** Wait until drive is ready to accept commands
; A,X,Y preserved
IDEDRDY	PHA
IDEDRDY0	LDA IDESTS	;read status register
	AND #$40		;select bit 6 (DRDY)
	BEQ IDEDRDY0	;loop if not set
	PLA
	RTS

; *** Wait until drive is ready to transfer data
; A,X,Y preserved
IDEDRQ	PHA
IDEDRQ0	LDA IDESTS	;read status register
	AND #$08		;select bit 3 (DRQ)
	BEQ IDEDRQ0	;loop if not set
	PLA
	RTS

; *** Byte-swap the data in the IDE buffer (512 bytes)
; Input: destination address stored at IDEBUFP
; A,X,Y preserved
IDESWAP	PHA
	TXA
	PHA
	TYA
	PHA
	LDA IDEBUFP	;make copy of IDEBUFP
	STA IDEBUFP1
	LDA IDEBUFP+1
	STA IDEBUFP1+1
	LDA #$00		;initialise counter
	STA ZTMP0
IDESWAP0	LDY #$00
	LDA (IDEBUFP1),Y	;get byte 1
	TAX		;store byte 1 in X
	LDY #$01
	LDA (IDEBUFP1),Y	;get byte 2
	LDY #$00
	STA (IDEBUFP1),Y	;write byte 2 over byte 1
	LDY #$01
	TXA		;retrieve byte 1 from X
	STA (IDEBUFP1),Y	;write byte 1 over byte 2
	INC ZTMP0		;increment count
	BEQ IDESWAP1	;quit when swapped all bytes
	LDA IDEBUFP1
	CLC
	ADC #$02		;advance pointer by two bytes
	STA IDEBUFP1
	BCC IDESWAP0	;check for high-byte rollover
	INC IDEBUFP1+1
	JMP IDESWAP0
IDESWAP1	PLA
	TAY
	PLA
	TAX
	PLA
	RTS

; *** Read block of data from device (512 bytes / 256 words)
; Input: destination address stored at IDEBUFP
; A,X,Y preserved
IDERBLK	PHA
	TXA
	PHA
	TYA
	PHA
	LDA IDEBUFP	;make copy of IDEBUFP
	STA IDEBUFP1
	LDA IDEBUFP+1
	STA IDEBUFP1+1
	LDX #$00
	LDY #$00
IDERBLK0	LDA IDEDATA	;read low byte
	STA (IDEBUFP1),Y	;store low byte
	INC IDEBUFP1	;advance pointer
	BNE IDERBLK1
	INC IDEBUFP1+1
IDERBLK1	LDA IDEHIGH	;read high byte from latch
	STA (IDEBUFP1),Y	;store high byte
	INC IDEBUFP1	;advance pointer
	BNE IDERBLK2
	INC IDEBUFP1+1
IDERBLK2	INX		;increment counter
	BNE IDERBLK0	;loop
	PLA
	TAY
	PLA
	TAX
	PLA
	RTS

; *** Write block of data to device (512 bytes / 256 words)
; Input: source address stored at IDEBUFP
; A,X,Y preserved
IDEWBLK	JSR IDESWAP	;swap bytes (interface needs hi-byte 1st)
	PHA
	TXA
	PHA
	TYA
	PHA
	LDA IDEBUFP	;make copy of IDEBUFP
	STA IDEBUFP1
	LDA IDEBUFP+1
	STA IDEBUFP1+1
	LDX #$00
	LDY #$00
IDEWBLK0	LDA (IDEBUFP1),Y	;read high byte
	STA IDEHIGH	;place high byte in latch
	INC IDEBUFP1	;advance pointer
	BNE IDEWBLK1
	INC IDEBUFP1+1
IDEWBLK1	LDA (IDEBUFP1),Y	;read low byte
	STA IDEDATA	;write word to device
	INC IDEBUFP1	;advance pointer
	BNE IDEWBLK2
	INC IDEBUFP1+1
IDEWBLK2	INX		;increment counter
	BNE IDEWBLK0	;loop
	PLA
	TAY
	PLA
	TAX
	PLA

; *** Read sector
; Input: LBA at IDELBA0-IDELBA3
;        destination address at IDEBUFP
IDERSEC	PHA
	JSR IDEBUSY	;make sure drive is ready
	LDA IDELBAF	;does drive support LBA?
	BEQ IDERSEC0	;no - jump
	LDA IDELBA0	;yes - load LBA values into registers
	STA IDESECT
	LDA IDELBA1
	STA IDECYLL
	LDA IDELBA2
	STA IDECYLH
	LDA IDELBA3
	ORA #$E0
	STA IDEDRHD
	JMP IDERSEC1
IDERSEC0	JSR LBA2CHS	;drive doesn't support LBA - convert to CHS

IDERSEC1	LDA #1
	STA IDESECC	;set sector count: 1 sector
	LDA #$20
	STA IDECMD	;set command: $20 = read sector(s)
	JSR IDEBUSY	;wait for command to finish
	JSR IDERBLK	;read 512 bytes into memory
	PLA
	RTS

; *** Write sector
; Input: LBA at IDELBA0-IDELBA3
;        source address at IDEBUFP
IDEWSEC	PHA
	JSR IDEBUSY	;make sure drive is ready
	LDA IDELBAF	;does drive support LBA?
	BEQ IDEWSEC0	;no - jump
	LDA IDELBA0	;yes - load LBA values into registers
	STA IDESECT
	LDA IDELBA1
	STA IDECYLL
	LDA IDELBA2
	STA IDECYLH
	LDA IDELBA3
	ORA #$E0
	STA IDEDRHD
	JMP IDEWSEC1
IDEWSEC0	JSR LBA2CHS	;drive doesn't support LBA - convert to CHS

IDEWSEC1	LDA #1
	STA IDESECC	;set sector count: 1 sector
	LDA #$30
	STA IDECMD	;set command: $30 = write sector(s)
	JSR IDEDRQ	;wait for drive to request data
	JSR IDEWBLK	;send 512 bytes
	PLA
	RTS

; *** Get drive identification
; A,X,Y preserved
IDEID	PHA
	TXA
	PHA
	TYA
	PHA

	JSR IDEBUSY
	LDA #$EC
	STA IDECMD	;send command $EC (identify drive)
	JSR IDEBUSY

	LDA #IDEBUF0	;set low byte of buffer address
	STA IDEBUFP
	LDA #IDEBUF0/256	;set high byte of buffer address
	STA IDEBUFP+1
	JSR IDERBLK	;read data into buffer

	JSR IDESWAP	;swap byte order (for some reason, ASCII strings
			; are sent with opposite-to-normal byte order)
	LDA #54		;word 27 = model number (40 chars)
	STA MSGBASE
	LDA #IDEBUF0/256
	STA MSGBASE+1
	JSR LCDCLR
	LDX #40
	JSR LCDSTRN	;print model number
	JSR IDESWAP	;swap byte order again
	JSR WAITKEY	;wait for keypress
	JSR LCDCLR
	LDA #'C'
	JSR LCDCHAR
	LDA #':'
	JSR LCDCHAR
	LDA IDEBUF0+3	;word 1 = cylinders
	JSR LCDHEX
	LDA IDEBUF0+2
	JSR LCDHEX
	LDA #' '
	JSR LCDCHAR
	LDA #'H'
	JSR LCDCHAR
	LDA #':'
	JSR LCDCHAR
	LDA IDEBUF0+6	;word 3 = heads
	STA ZTMP0		;store for SPC calculation
	JSR LCDHEX
	LDA #' '
	JSR LCDCHAR
	LDA #'S'
	JSR LCDCHAR
	LDA #':'
	JSR LCDCHAR
	LDA IDEBUF0+12	;word 6 = sectors
	STA ZTMP2		;store for SPC calculation
	STA IDESPT	;also store as SPT
	JSR LCDHEX
	LDA #' '
	JSR LCDCHAR
	JSR LCDCHAR
	LDA #0		;setup high bytes
	STA ZTMP1
	STA ZTMP3
	JSR MUL16		;calculate SPC = H * S
	LDA ZTMP1
	STA IDESPC+1
	JSR LCDHEX
	LDA ZTMP0
	STA IDESPC
	JSR LCDHEX
	LDA #0
	STA ZTMP2
	STA ZTMP3
	STA ZTMP6
	STA ZTMP7
	LDA IDEBUF0+2
	STA ZTMP4
	LDA IDEBUF0+3
	STA ZTMP5
	JSR MUL32		;calculate total number of sectors = SPC * C
	LDA #' '
	JSR LCDCHAR
	JSR LCDCHAR
	LDA ZTMP3
	STA IDESIZE+3
	JSR LCDHEX
	LDA ZTMP2
	STA IDESIZE+2
	JSR LCDHEX
	LDA ZTMP1
	STA IDESIZE+1
	JSR LCDHEX
	LDA ZTMP0
	STA IDESIZE
	JSR LCDHEX

	;does drive support LBA? (word 49 bit 9)
	LDY #0
	LDA #TEXTCHS
	STA MSGBASE
	LDA #TEXTCHS/256
	STA MSGBASE+1
	LDA IDEBUF0+99
	AND #$02
	BEQ IDEID1
	LDY #1
	LDA #TEXTLBA
	STA MSGBASE
	LDA #TEXTLBA/256
	STA MSGBASE+1
IDEID1	STY IDELBAF
	LDA #' '
	JSR LCDCHAR
	JSR LCDCHAR
	JSR LCDSTR

	JSR WAITKEY	;wait for keypress

	PLA
	TAY
	PLA
	TAX
	PLA
	RTS

TEXTCHS	fcs "CHS"
	.byte $00
TEXTLBA	fcs "LBA"
	.byte $00

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -