-
Notifications
You must be signed in to change notification settings - Fork 0
/
storage_sub.asm
294 lines (294 loc) · 5.25 KB
/
storage_sub.asm
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
%ifndef _STORAGE_SUB_ASM_
%define _STORAGE_SUB_ASM_
; --- modules ---
%include "type_macros.asm"
%include "disk_sub.asm"
; --- macros ---
%define MAX_SEC_PER_OP 128 ; max sector per operation
%define MAX_TRY_PER_OP 5
; Set and initialize drive
; dl <- drive number
%macro STORAGE_SET_DRIVE 0
pusha
mov byte [storage_data.drive_number], dl
push es
mov ah, 0x08
xor di, di
mov es, di
int 0x13
pop es
jc %%fail
mov byte [storage_data.initialized], 1
inc dh
mov byte [storage_data.head_count], dh
mov bx, cx
and bl, 0x3f
mov byte [storage_data.sector_count], bl
mov bx, cx
and bx, 0xffc0
ror bx, 8
inc bx
mov word [storage_data.cylinder_count], bx
jmp %%end
%%fail :
mov byte [storage_data.initialized], 0
%%end :
popa
%endmacro
; Read sectors & ensure data intergrity
; al <- number of sectors {max 128}
; ch <- low eight bits of cylinder number
; cl <- sector number (1-63 bits 0-5)
; dh <- starting head on disk
; es : bx <- data buffer for loaded data
; cf -> set on fail
%macro STORAGE_DISK_READ 0
pusha
push es
mov byte dl, [storage_data.initialized]
cmp dl, 0
je %%fail
mov byte dl, [storage_data.drive_number]
movzx si, al ; si = last sector count requested
mov di, MAX_TRY_PER_OP ; di = try count
%%loop :
DISK_READ
jnc %%success
xor ah, ah ; ax/al = number of sectors read
pusha
mov dl, 20 ; SECTOR_SIZE >> 4
mul dl
mov bx, es
add bx, ax
mov es, bx
popa
call storageAddCHS
sub si, ax
mov ax, si
dec di
jz %%fail
cmp al, 0
jne %%loop
%%success :
clc
jmp %%end
%%fail :
stc
%%end :
pop es
popa
%endmacro
; Write sectors & ensure data intergrity
; al <- number of sectors {max 128}
; ch <- low eight bits of cylinder number
; cl <- sector number (1-63 bits 0-5)
; dh <- starting head on disk
; es : bx <- data to be written on disk
; cf -> set on fail
%macro STORAGE_DISK_WRITE 0
pusha
push es
mov byte dl, [storage_data.initialized]
cmp dl, 0
je %%fail
mov byte dl, [storage_data.drive_number]
movzx si, al ; si = last sector count requested
mov di, MAX_TRY_PER_OP ; di = try count
%%loop :
DISK_WRITE
jnc %%success
xor ah, ah ; ax/al = number of sectors written
pusha
mov dl, 20 ; SECTOR_SIZE >> 4
mul dl
mov bx, es
add bx, ax
mov es, bx
popa
call storageAddCHS
sub si, ax
mov ax, si
dec di
jz %%fail
cmp al, 0
jne %%loop
%%success :
clc
jmp %%end
%%fail :
stc
%%end :
pop es
popa
%endmacro
; --- data ---
storage_data :
.initialized :
db 0 ; 0 if false, else true
.drive_number :
db 0
.head_count :
db 0
.cylinder_count :
dw 0
.sector_count :
db 0
; --- subroutine ---
; Read sectors into memory
; ax <- number of sectors
; ch <- low eight bits of cylinder number
; cl <- sector number (1-63 bits 0-5)
; dh <- starting head on disk
; es : bx <- data buffer for loaded data
; cf -> set on fail
storageRead :
pusha
push es
mov byte dl, [storage_data.initialized]
cmp dl, 0
je .fail
push dx
mov dl, MAX_SEC_PER_OP
div dl
pop dx
xchg al, ah ; ah = number of 128 sectors ; al = number of sectors
.loop :
cmp ah, 0
je .loop_end
push ax
mov al, MAX_SEC_PER_OP
STORAGE_DISK_READ
pop ax
jc .fail
dec ah
push ax
mov ax, MAX_SEC_PER_OP
call storageAddCHS
pop ax
jc .fail
mov bx, es
add bx, ((MAX_SEC_PER_OP * SECTOR_SIZE) >> 4)
mov es, bx
mov bx, ((MAX_SEC_PER_OP * SECTOR_SIZE) & 0x0f) ; digits that are shifted out
jmp .loop
.loop_end :
clc
cmp al, 0
je .success
STORAGE_DISK_READ
jc .fail
.success :
clc
jmp .end
.fail :
stc
.end :
pop es
popa
ret
; write sectors into disk
; al <- number of sectors to write (nonzero, max 128)
; ch <- low eight bits of cylinder number
; cl <- sector number (1-63 bits 0-5)
; dh <- head number
; dl <- drive number
; es : bx <- data to be written on disk
; cf -> set on fail
storageWrite :
pusha
push es
mov byte dl, [storage_data.initialized]
cmp dl, 0
je .fail
push dx
mov dl, MAX_SEC_PER_OP
div dl
pop dx
xchg al, ah ; ah = number of 128 sectors ; al = number of sectors
.loop :
cmp ah, 0
je .loop_end
push ax
mov al, MAX_SEC_PER_OP
STORAGE_DISK_WRITE
pop ax
jc .fail
dec ah
push ax
mov ax, MAX_SEC_PER_OP
call storageAddCHS
pop ax
jc .fail
mov bx, es
add bx, ((MAX_SEC_PER_OP * SECTOR_SIZE) >> 4)
mov es, bx
mov bx, ((MAX_SEC_PER_OP * SECTOR_SIZE) & 0x0f) ; digits that are shifted out
jmp .loop
.loop_end :
clc
cmp al, 0
je .success
STORAGE_DISK_WRITE
jc .fail
.success :
clc
jmp .end
.fail :
stc
.end :
pop es
popa
ret
; Add to CHS address
; ax -> value added
; cx <- cylinder sector
; dh <- head
; cx -> new cylinder sector
; dh -> new head
; cf -> set if fail
storageAddCHS :
push ax
push bx
mov byte bl, [storage_data.initialized]
cmp bl, 0
je .fail
xor bx, bx
mov byte bl, [storage_data.sector_count] ; bx/bl = sector per track
push dx
mov dx, cx
and dx, 0x3f ; dx/dl = currect sector
add dx, ax
mov ax, dx
pop dx
div bl ; ah = new sector ; al = cylinder to be added
mov word bx, [storage_data.cylinder_count] ; bx = cylinder count
push dx
mov dx, cx
and dx, 0xffc0
ror dx, 8
movzx cx, ah ; cx = new sector
xor ah, ah
add ax, dx ; ax = new cylinder
pop dx
.subtract_loop :
cmp ax, bx
jl .subtract_loop_end
sub ax, bx
inc dh
jmp .subtract_loop
.subtract_loop_end :
mov bh, [storage_data.head_count]
cmp dh, bh
ja .fail
.success :
rol ax, 8
or cx, ax
clc
jmp .end
.fail :
stc
.end :
pop bx
pop ax
ret
%endif ; _STORAGE_SUB_ASM_