-
Notifications
You must be signed in to change notification settings - Fork 1
/
cf.z80
126 lines (119 loc) · 3.27 KB
/
cf.z80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
; Register definitions
.DATA: equ CFBASE + 0x00 ; Data (R/W)
.ERR: equ CFBASE + 0x01 ; Error register (R)
.FEAT: equ CFBASE + 0x01 ; Features (W)
.SECCO: equ CFBASE + 0x02 ; Sector count (R/W)
.SECNO: equ CFBASE + 0x03 ; Sector number (R/W, CHS mode)
.LBA0: equ CFBASE + 0x03 ; LBA bits 0-7 (R/W, LBA mode)
.CYLLO: equ CFBASE + 0x04 ; Cylinder low (R/W, CHS mode)
.LBA1: equ CFBASE + 0x04 ; LBA bits 8-15 (R/W, LBA mode)
.CYLHI: equ CFBASE + 0x05 ; Cylinder high (R/W, CHS mode)
.LBA2: equ CFBASE + 0x05 ; LBA bits 16-23 (R/W, LBA mode)
.DRHD: equ CFBASE + 0x06 ; Drive/head (R/W, CHS mode)
.LBA3: equ CFBASE + 0x06 ; LBA bits 24-27 (R/W, LBA mode)
.STAT: equ CFBASE + 0x07 ; Status (R)
.CMD: equ CFBASE + 0x07 ; Command (W)
CfSetup:
; Activate 8 bit data transfer mode
call WaitBusy
ld a, $01 ; Set features register to enable 8 bit
out (.FEAT), a
call WaitBusy
ld a, $EF ; Send set features command
out (.CMD), a
call WaitBusy
ret
CfReadSectors:
push af ; Save sector count
call SetSectorCount
call SetLBA
call SendReadCommand
pop af ; Restore sector count
ld b, a ; Move sector count to B
CfReadLoop:
call WaitBusyData
ld c, .DATA ; port address
push bc
ld b, 0 ; read 256 bytes at a time
inir ; Read first half of sector
inir ; Read second half of sector
pop bc
djnz CfReadLoop ; Loop
ret
CfWriteSectors:
push af ; Save sector count
call SetSectorCount
call SetLBA
call SendWriteCommand
pop af ; Restore sector count
ld b, a
CfWriteLoop:
call WaitBusyData
ld c, .DATA ; port address
push bc
ld b, 0 ; read 256 bytes at a time
otir ; Write first half of sector
otir ; Write second half of sector
pop bc
djnz CfWriteLoop
ret
SetLBA:
; Set up LBA address for start of disk
; Addresses 0, 1, 2 are in regs B, C, D and E
call WaitBusy
ld a, c
out (.LBA0), a ; Set LBA addresses 0
call WaitBusy
ld a, b
out (.LBA1), a
call WaitBusy
ld a, e
out (.LBA2), a
call WaitBusy
ld a, d
and 00001111b ; mask off non-address bits
or 11100000b ; set LBA mode, drive 0
out (.LBA3), a
call WaitBusy
ret
SetSectorCount:
push af
call WaitBusy
pop af
out (.SECCO), a
ret
SendReadCommand:
call WaitBusyReady ; Make sure drive is ready for command
ld a, $20 ; Prepare read command
out (.CMD), a ; Send read command
call WaitBusyData ; Wait until data is ready to be read
in a, (.STAT) ; Read status
and %00000001 ; mask off error bit
jp nz, SendReadCommand ; Try again if error
ret
SendWriteCommand:
call WaitBusyReady ; Make sure drive is ready for command
ld a, $30 ; Prepare read command
out (.CMD), a ; Send read command
call WaitBusyData ; Wait until data is ready to be read
in a, (.STAT) ; Read status
and %00000001 ; mask off error bit
jp nz, SendWriteCommand ; Try again if error
ret
WaitBusy:
in a, (.STAT) ; Read status
and %10000000 ;mask off busy bit
jr nz, WaitBusy ;we want busy(7) to be 0
ret
WaitBusyReady:
in a, (.STAT) ; Read status
and %11000000 ;mask off busy and rdy bits
xor %01000000 ;we want busy(7) to be 0 and rdy(6) to be 1
jr nz, WaitBusyReady
ret
WaitBusyData:
in a, (.STAT) ; Read status
and %10001000 ;mask off busy and drq bits
xor %00001000 ;we want busy(7) to be 0 and drq(3) to be 1
jr nz, WaitBusyData
ret