Files
Z8C-Homebrew-Computer/OperatingSystem/monitor_v2/include/kdrv_ideif.s
2024-01-12 13:29:20 +01:00

449 lines
11 KiB
ArmAsm

;----------------------------------------------------------------
;BIOS Driver for IDE Access
;by Dennis Gunia (01/2023)
;----------------------------------------------------------------
;================================================================
; IDE commands
;================================================================
IDE_CMD_IDENT .EQU 0xEC ;Identify drive.
IDE_CMD_READSEC .EQU 0x20 ;Read sectors.
;================================================================
; IDE Variables
;================================================================
phase var_idebuffer
MEM_IDE_DEVICE:
defs 1
MEM_IDE_STATUS:
defs 1 ;1Byte: 0x00 if status is okay
MEM_IDE_PARTITION:
defs 4 ;4*16Bytes: LBA first sector
MEM_IDE_POINTER:
defs 4 ;4*16Bytes: LBA first sector
MEM_IDE_DEV_TABLE:
defs 16*4
MEM_IDE_SELECTED:
defs 1
MEM_IDE_STRING_0:
defs 40
MEM_IDE_STRING_1:
defs 40
MEM_IDE_STRING_2:
defs 40
MEM_IDE_STRING_3:
defs 40
MEM_IDE_BUFFER:
defs 512
MEM_IDE_FSBUFFER:
defs 256
dephase
;DEV-Table layout
;<STATUS> <TYPE> <FIRST-SECTOR (4-byte)> <Length (4-byte)> <I/O Addr> <Master/Slave> 0x00 0x00
;Status: 0x00 -> Ready
; 0x01 -> Not found
; 0x02 -> No supported filesystem
;I/O Addr: Base addr of 82C55
;Type: File system type
IDE_DEV_TABLE:
db 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, [MEM_IDE_STRING_0], [MEM_IDE_STRING_0]>>8, 0x00, 0x00
db 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, [MEM_IDE_STRING_1], [MEM_IDE_STRING_1]>>8, 0x00, 0x00
db 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, [MEM_IDE_STRING_2], [MEM_IDE_STRING_2]>>8, 0x00, 0x00
db 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, [MEM_IDE_STRING_3], [MEM_IDE_STRING_3]>>8, 0x00, 0x00
;================================================================
; IDE funtions
;================================================================
;------------------------------------------------------------------------------
; ideif_init_table
;
; initializes drive table
;------------------------------------------------------------------------------
ideif_init_devtable:
;copy default values to ram
ld hl,[IDE_DEV_TABLE]
ld de,[MEM_IDE_DEV_TABLE]
ld bc,16*4
ldir
;set selected device
ld a,0
ld (MEM_IDE_SELECTED),a
;set empty names
xor a
ld (MEM_IDE_STRING_0),a
ld (MEM_IDE_STRING_1),a
ld (MEM_IDE_STRING_2),a
ld (MEM_IDE_STRING_3),a
ret
;------------------------------------------------------------------------------
; ideif_prnt_devtable
;
; prints drive table
;------------------------------------------------------------------------------
ideif_prnt_devtable:
call print_newLine
ld hl,[_ideif_prnt_devtable_hdr]
call print_str
ld hl,[MEM_IDE_DEV_TABLE]
ld b,0 ;device number
_ideif_prnt_devtable_l1: ;loop 1 -> for each device
;print if selected
ld a,(MEM_IDE_SELECTED)
cp b
jp z,_ideif_prnt_devtable_l1_sel
ld a, ' '
jr _ideif_prnt_devtable_l1_nxt
_ideif_prnt_devtable_l1_sel:
ld a, '*'
_ideif_prnt_devtable_l1_nxt:
call print_char
;print drive letter
ld a,b
add 69 ;offset letter to D
call print_char
ld a, ':'
call print_char
ld a, ' '
call print_char
;print status
push hl
ld a,(HL)
or a
jr z, _ideif_prnt_devtable_l1_s00
cp 0x01
jr z, _ideif_prnt_devtable_l1_s01
cp 0x02
jr z, _ideif_prnt_devtable_l1_s02
cp 0xFF
jr z, _ideif_prnt_devtable_l1_sFF
jr _ideif_prnt_devtable_l1_sFF
_ideif_prnt_devtable_l1_s00
ld hl,[_ideif_prnt_devtable_s00]
jr _ideif_prnt_devtable_l1_es
_ideif_prnt_devtable_l1_s01
ld hl,[_ideif_prnt_devtable_s01]
jr _ideif_prnt_devtable_l1_es
_ideif_prnt_devtable_l1_s02
ld hl,[_ideif_prnt_devtable_s02]
jr _ideif_prnt_devtable_l1_es
_ideif_prnt_devtable_l1_sFF
ld hl,[_ideif_prnt_devtable_sFF]
_ideif_prnt_devtable_l1_es
call print_str
pop hl
inc hl
;print FS-Type
ld a,'0'
call print_char
ld a,'x'
call print_char
ld a,(HL)
call print_a_hex
ld a,' '
call print_char
inc hl
;print first sector
push hl
pop ix
inc hl
inc hl
inc hl
inc hl
inc hl
inc hl
inc hl
inc hl
ld a,(ix+3)
call print_a_hex
ld a,(ix+2)
call print_a_hex
ld a,(ix+1)
call print_a_hex
ld a,(ix+0)
call print_a_hex
ld a,' '
call print_char
;print length
ld a,(ix+7)
call print_a_hex
ld a,(ix+6)
call print_a_hex
ld a,(ix+5)
call print_a_hex
ld a,(ix+4)
call print_a_hex
ld a,' '
call print_char
;print Port
ld a,'0'
call print_char
ld a,'x'
call print_char
ld a,(HL)
call print_a_hex
ld a,' '
call print_char
inc hl
;print M/S
ld a,(HL)
push hl
or a
jp z,_ideif_prnt_devtable_l1_ms
ld hl,[_ideif_prnt_devtable_slave]
jp _ideif_prnt_devtable_l1_e2
_ideif_prnt_devtable_l1_ms
ld hl,[_ideif_prnt_devtable_master]
_ideif_prnt_devtable_l1_e2
call print_str
pop hl
inc hl
;print str
push bc
ld a,(hl)
ld c,a
inc hl
ld a,(hl)
ld b,a
inc hl
push hl
ld h,b
ld l,c
call print_str
call print_newLine
pop hl
pop bc
;next
inc hl
inc hl
inc b
ld a,b
cp 4
ret z
jp _ideif_prnt_devtable_l1
;------------------------------------------------------------------------------
; ideif_init_drive
;
; initializes selected drive in table
;------------------------------------------------------------------------------
ideif_init_drive:
call ideif_get_drv_pointer
; load addresses. not used atm
;ld a,(IX+6) ;load IO Addr
;ld d,a
;ld a,(IX+7) ;load Master/Slave bit
;ld e,a
call ide_reset
ld bc, 0x5FFF ;preload timeout counter
_ideif_init_drive_loop:
ld b, IDE_REG_CMDSTS
call ide_regread_8 ;read drive status register
or a
jr z,_ideif_init_drive_nodrv ;no drive found
bit 6,a
jr nz, _ideif_init_drive_found
dec de
ld a,d
or e
jr z, _ideif_init_drive_nodrv
jr _ideif_init_drive_loop
_ideif_init_drive_nodrv:
ld(ix+0),0x01
ret
_ideif_init_drive_found:
ld (ix+0),0x02
;get drive name
ld b, IDE_REG_CMDSTS ;Get drive identification
ld a, IDE_CMD_IDENT
call ide_regwrite_8 ;Write command to drive
ld hl, MEM_IDE_BUFFER ;set read/write buffer start address
call ide_readsector_256 ;read 256 words from device
ld hl,MEM_IDE_BUFFER + 54 ;print device serial
ld a,(ix+12) ;load str pointer into de
ld e,a
ld a,(ix+13)
ld d,a
ld bc,40 ;copy 40 char
ldir
;get partition table
;read bootsector
ld a,1 ;read 1 sector
ld B,IDE_REG_SECTOR
call ide_regwrite_8
ld a,1 ;read sector 0
ld b,IDE_REG_SSECTOR
call ide_regwrite_8
ld a,0 ;read cylinder 0
ld b,IDE_REG_LCYL
call ide_regwrite_8
ld a,0
ld b,IDE_REG_HCYL
call ide_regwrite_8
ld a,10100000b ;read head 0
ld b,IDE_REG_HEAD
call ide_regwrite_8
ld a,IDE_CMD_READSEC ;send read command
ld b,IDE_REG_CMDSTS
call ide_regwrite_8
ld hl, MEM_IDE_BUFFER ;set read/write buffer start address
call ide_readsector_512_inv ;read 256 words from device
;prepare partitions
ld b,4 ;Partition table length
ld c,0 ;Partition ID counter
ld iy,MEM_IDE_BUFFER+446 ;Load offest of first partition table entry
_ideif_init_drive_prt_l1:
ld a,(iy+4) ;load status byte
or a
jp NZ, _ideif_init_drive_prt_fnd ;If not zero, jump to print function
jp _ideif_init_drive_prt_ln
_ideif_init_drive_prt_ln:
ld de,16
add iy,de
djnz _ideif_init_drive_prt_l1
ret
_ideif_init_drive_prt_fnd;
ld a,(iy+4)
ld (ix+1),a ;store partition type
cp 0x0E ;if not 0xE0, continue with next entry
jr nz, _ideif_init_drive_prt_ln
;get start LBA
ld a,(iy+0x08)
ld (ix+0x02),a
ld a,(iy+0x09)
ld (ix+0x03),a
ld a,(iy+0x0A)
ld (ix+0x04),a
ld a,(iy+0x0B)
ld (ix+0x05),a
ld (ix+0),0x00
;get count LBA
ld a,(iy+0x0C)
ld (ix+0x06),a
ld a,(iy+0x0D)
ld (ix+0x07),a
ld a,(iy+0x0E)
ld (ix+0x08),a
ld a,(iy+0x0F)
ld (ix+0x09),a
ld (ix+0),0x00
ret
;------------------------------------------------------------------------------
; ideif_get_drv_pointer
;
; gets pointer to selected drive in table in IX
;------------------------------------------------------------------------------
ideif_get_drv_pointer:
push af
push bc
;get selected drive
ld a,(MEM_IDE_SELECTED)
;multiply a *8
rlca ;*2
rlca ;*4
rlca ;*8
ld b,0
ld c,a
ld ix,[MEM_IDE_DEV_TABLE]
add ix,bc
pop bc
pop af
ret
;------------------------------------------------------------------------------
; ideif_init_all
;
; initializes interface
;------------------------------------------------------------------------------
ideif_init_all:
ld hl, [str_dev_waitready]
call print_str ;print waiting message
call ideif_init_devtable
call ideif_init_drive
ld hl, [str_dev_done]
call print_str
RET
;------------------------------------------------------------------------------
; ideif_drv_sel
;
; Selects drive from table and initializes the fat16 file system
; A contains drive id
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; read_lba_sector
;
; Reads A*512 byte sector into memory
; HL contains pointer to LBA address
; A contains sector count
;------------------------------------------------------------------------------
read_lba_sector:
LD B,IDE_REG_SECTOR ;amount of sectores
CALL ide_regwrite_8
LD A,(HL)
LD B,IDE_REG_LBA0
CALL ide_regwrite_8
INC HL
LD A,(HL)
LD B,IDE_REG_LBA1
CALL ide_regwrite_8
INC HL
LD A,(HL)
LD B,IDE_REG_LBA2
CALL ide_regwrite_8
INC HL
LD A,(HL)
AND 00001111b
OR 11100000b
LD B,IDE_REG_LBA3
CALL ide_regwrite_8
LD A,IDE_CMD_READSEC ;send read command
LD B,IDE_REG_CMDSTS
CALL ide_regwrite_8
LD HL,MEM_IDE_BUFFER ;set read/write buffer start address
call ide_readsector_512_inv ;read 256 words from device
ret
;================================================================
; IDE strings
;===============================================================
str_dev_waitready:
db 13,10,"Detecting drives ... ",0
str_dev_done:
db "done!",13,10,0
_ideif_prnt_devtable_hdr:
db "DRV Status Type LBA Length Port M/S Name",10,13,0
_ideif_prnt_devtable_s00:
db "Avail ",0
_ideif_prnt_devtable_s01:
db "Not Found ",0
_ideif_prnt_devtable_s02:
db "Unkown FS ",0
_ideif_prnt_devtable_sFF:
db "Ctrl. Err ",0
_ideif_prnt_devtable_master:
db "Master ",0
_ideif_prnt_devtable_slave:
db "Slave ",0