-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBIOSIDE.MAC
479 lines (472 loc) · 12.9 KB
/
BIOSIDE.MAC
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
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
; IDE BIOS best dos
;
PRO_SYS EQU 56H ; registr uprawleniq
PRO_DATAH EQU 57H ; st.bajt registra dannyh
PRO_DATAL EQU 58H ; ml.bajt registra dannyh
PRO_ERREG EQU 59H ; registr o{ibok
PRO_SEC_CNT EQU 5Ah ; // s4et4ik seektorow - W // adr=2
PRO_SECTOR EQU 5Bh ; // registr sektora - W // adr=3
PRO_CYL_LSB EQU 5Ch ; // ml.bajt nom.cilindra - W // adr=4
PRO_CYL_MSB EQU 5Dh ; // st.bajt nom.cilindra - W // adr=5
PRO_HEAD EQU 5Eh ; // registr golowki/ustrojstwa - W // adr=6
PRO_STAT EQU 5FH ; registr sostoqniq
PRO_COMAND EQU 5FH ; registr komand
;
ide_8255 equ 0F600h ; 0F500h ;PPA base address
ide_8255_lsb equ ide_8255+2 ;pC - lower 8 bits
ide_8255_msb equ ide_8255+1 ;pB - upper 8 bits
ide_8255_ctl equ ide_8255 ;pA - control lines
ide_8255_cfg equ ide_8255+3 ; 8255 configuration register
rd_ide_8255 equ 10001011b ;ide_8255_ctl out, ide_8255_lsb/msb input
wr_ide_8255 equ 10000000b ;all three ports output
;
ide_a0_line equ 01h ;direct from 8255 to ide interface
ide_a1_line equ 02h ;direct from 8255 to ide interface
ide_a2_line equ 04h ;direct from 8255 to ide interface
ide_cs0_line equ 08h ;inverter between 8255 and ide interface
ide_cs1_line equ 10h ;inverter between 8255 and ide interface
ide_wr_line equ 20h ;inverter between 8255 and ide interface
ide_rd_line equ 40h ;inverter between 8255 and ide interface
ide_rst_line equ 80h ;inverter between 8255 and ide interface
;
ide_data equ ide_cs0_line
ide_err equ ide_cs0_line + ide_a0_line
ide_sec_cnt equ ide_cs0_line + ide_a1_line
ide_sector equ ide_cs0_line + ide_a1_line + ide_a0_line
ide_cyl_lsb equ ide_cs0_line + ide_a2_line
ide_cyl_msb equ ide_cs0_line + ide_a2_line + ide_a0_line
ide_head equ ide_cs0_line + ide_a2_line + ide_a1_line
ide_command equ ide_cs0_line + ide_a2_line + ide_a1_line + ide_a0_line
ide_status equ ide_cs0_line + ide_a2_line + ide_a1_line + ide_a0_line
ide_control equ ide_cs1_line + ide_a2_line + ide_a1_line
ide_astatus equ ide_cs1_line + ide_a2_line + ide_a1_line + ide_a0_line
;
;IDE Command Constants. These should never change.
;
ide_cmd_read equ 20h
ide_cmd_write equ 30h
ide_cmd_id equ 0ECh
ide_cmd_none equ 0
;
intinchl equ 2756 ; initial constant for 10ms timing loop
;
; M_RDIDE read 512b sector from ide, inp: HL=DriveInfo_array+8,
; d=0=master; d=10h=slave
; e=command_mode (ide_cmd_none,ide_cmd_read,ide_cmd_id)
; Return: acc=zero on success, non-zero for an error
; de=IDE PPA base address (0F500h, F600h, etc)
; hl=buffer+512
;
;M_RDIDE EQU 0F834h
;
;
x_rdide:ld e, ide_cmd_read
y_rdide:
; call MDI ; saves all registers
push de
ld a, d
and 1
jr z, _rdhdd
ld a, ide_cmd_read
cp e
call z, sd_read
jr _rdret
_rdhdd: call z_rdide
_rdret: pop de
ret
;
; ðÒÏÞÉÔÁÔØ ÓÅËÔÏÒ, ÓÏÈÒÁÎÉÔØ ÁÄÒÅÓ ÓÅËÔÏÒÁ × LBABUF
; ÷ÙÈÏÄ: Z=ok, NZ=error
;
readide:
call idedevice ; d: 0=Master, 10h=slave;
ld hl, MasterInfo+8
call x_rdide ; e:=ide_cmd_read, saves de (d: 0=Master, 10h=slave)
ld b, 0FFh ; unreal LBA - force reread on access
jr nz, readide1 ; if error
ld bc, (MasterInfo+7)
readide1:
ld hl, (PAR_IDE) ; hl=LBABUF
dec hl ; hl=IDEDEVx
ld (hl), d ; put device flag (master=0/slave=10h) to IDEDEVx
inc hl
ld de, (MasterInfo+5)
ld (hl), e
inc hl
ld (hl), d
inc hl
ld (hl), c
inc hl
ld (hl), b
ret
;
idebuf_offset:
ld a, (IDEBUF_OFFS) ; a=0..3
ld hl, (PAR_IDE+4) ; hl=IDEBUF
ld bc, 80h ; calculate buffer offset
iboffs: or a
ret z ; return if a=-1
dec a
add hl, bc
jr iboffs
;
WRITESEC:
ld a,d
ld (DMABANK),a
call ZDI
LD A,(WORKDISK)
CP 2
JP c, WRITEFLOPPY ; Device0 = Floppy0, Device1 = Floppy1
JP z, WRVDISK ; Device2 = VDISK
cp 6 ; Device6 = ROMDISK
jp nc, copyerr ; ROM writing not acceptable
;
; Device3..Device5 = IDE/SD slot 0..2
WRIDE: LD A, d ; d=(DMABANK)
cp WORKPAGE
jr z, WRIDE00
LD DE,MOVEBUF
CALL @@BLDR80HLDMA ; éú ðïìøúï÷áôåìøóëïçï DMA
WRIDE00:CALL SEC2LBA ; OUT: HL=SECTOR_ADDRESS, A=SECTOR_BANK, B=0
jr nz, get_err1
CALL cmp_lba ; hl=MasterInfo+8
push af
call nz, readide ; read IDE if attemp to write nonbuffered sector
jr nz, get_err2
call idebuf_offset ; hl=128b segment address, bc=080h
ex de,hl
LD HL,MOVEBUF
LD A,(DMABANK)
cp WORKPAGE
jr nz, WRIDE01
LD HL,(DMAPOINT)
WRIDE01:ldir
call idedevice ; d: 0=Master, 10h=slave, 1,3=SDCARD
ld hl, MasterInfo+8
;
; ide<->sd switch
;
bit 0, d
jr z, _wrhdd
pop af
; call MDI
jp sd_write
; jp MEI
_wrhdd:
pop af
; jr nz, wride0 ; 20160918 temporary! previously idea was what LBAnum allready setted while buffering (readsec)
;
x_wride:ld e, ide_cmd_write
call y_rdide ; e=ide_cmd_write -> only set LBA position, wait DRQ
jr nz, get_err1
wride0: ld hl, (PAR_IDE+4) ; hl=IDEBUF
;
; Write a block of 512 bytes [from buffer at (hl)] to the drive
;
write_data:
; call MDI
IF IDEPRO
ld b,0
WRC0: ld c,(hl)
inc hl
ld a,(hl)
out (PRO_DATAH),a
inc hl
ld a,c
out (PRO_DATAL),a
djnz WRC0
ELSE
ld a, wr_ide_8255
@@P0: ld (ide_8255_cfg), a ; config 8255 chip, write mode
ld bc, ide_data ; b=0, c = ide register address
@@P1: ld de, ide_8255_ctl
wrblk2: ld a, (hl)
@@P2: ld (ide_8255_lsb), a ; drive lower lines with lsb
inc hl
ld a, (hl)
@@P3: ld (ide_8255_msb), a ; drive upper lines with msb
ld a, c
ld (de), a ; drive address onto control lines
or ide_wr_line
ld (de), a ; assert write pin
inc hl ; delay 6 tstates
ld a, c ; delay 4 tstates, total ~2.5 mks
ld (de), a ; deassert write pin
djnz wrblk2
ld a, rd_ide_8255
@@P4: ld (ide_8255_cfg), a ; config 8255 chip, read mode
ENDIF
;
; wait until the write is complete
;
call ide_wait_not_busy
; call MEI
jr z, get_err1 ; if Busy
xor a
ret
;
get_err2:pop af
get_err1:
get_err:xor a
rdretff:dec a ; error = 0FFh
ret
;
RDIDE: ; Device3..Device5 = IDE/SD slot 0..2
CALL SEC2LBA
jr nz, get_err1
CALL cmp_lba
call nz, readide ; read IDE if attemp to read nonbuffered sector
jr nz, get_err1
call idebuf_offset ; hl=128b segment address, bc=080h
LD A,(DMABANK)
cp WORKPAGE
jr z, @@BLDR80DEDMA
LD DE,MOVEBUF
push de
ldir ; ÷ï ÷òåíåîîùê âõæåò
pop HL ; HL=MOVEBUF
;
@@BLDR80DEDMA:
LD DE,(DMAPOINT)
jr @@BLDR80
@@BLDR80HLDMA:
LD HL,(DMAPOINT)
@@BLDR80:
ld bc, 80h
@@BLDR: LD A,(DMABANK)
CP WORKPAGE
JP NZ,MOVEADRSP
@@BLDRET:
LDIR
xor a
RET
;
; read a HDD sector, specified by the 4 bytes in "lba"
; Input: HL=DriveInfo_array+8,
; d=( 0=master, 10h=slave )
; e=command_mode (ide_cmd_read, ide_cmd_id, ide_cmd_write)
; Return, acc=zero (Z) on success, non-zero (NZ) for an error
;
;get_err:xor a
;rdretff:dec a ; ld a, ide_error_busy
; ret
z_rdide:push de
call ide_wait_not_busy ; make sure drive is ready
pop de
jr z, rdretff ; if a=0,Z=true
push de
call wr_lba ; tell it which sector we want
dec hl
ld a, (hl)
dec hl
ld l, (hl)
ld h, a ; hl = buffer addres from DriveInfo_array
call ide_wait_not_busy ; make sure drive is ready
pop de
zgeterr:jr z, get_err
rrca
cgeterr:jr c, get_err
IF IDEPRO
ld a,e
out (PRO_COMAND),a
push de
ELSE
ld a, ide_command
push de
call ide_wr_8 ; ask the drive to read it
ENDIF
call ide_wait_drq ; wait until it's got the data
pop de
jr z, zgeterr
rrca
jr c, cgeterr
ld a, e
sub ide_cmd_write
ret z
;
; Read a block of 512 bytes (one sector) from the drive
; and store it in memory (hl)
;
read_data: ; hl=buffer address
IF IDEPRO
ld b,0
RDC0: in a,(PRO_DATAL)
ld (hl),a
inc hl
in a,(PRO_DATAH)
ld (hl),a
inc hl
djnz RDC0
xor a
ret
ELSE
@@P7: ld de, ide_8255_ctl ; 0F500h
ld bc, ide_data ; b=0, c=ide_data
rdblk2: ld a, c
ld (de), a ; drive address onto control lines
or ide_rd_line
ld (de), a ; assert read pin on control lines
@@P8: ld a, (ide_8255_lsb) ; read the lower byte
ld (hl), a
inc hl
@@P9: ld a, (ide_8255_msb) ; read the upper byte
ld (hl), a
inc hl
xor a
ld (de), a ; deassert all control pins
djnz rdblk2
ret
ENDIF
;
; Wait for NOT_BUSY. if Z at exit => error(timeout, busy), NZ=OK
;
ide_wait_not_busy:
ld b, 0 ; rdy_repeat=256
ide_wbsy:
IF IDEPRO
in a,(PRO_STAT)
ELSE
ld a, ide_status ; wait for RDY bit to be set
call ide_rd_8
ENDIF
cpl
and 10000000b
ret nz ; nz = OK
call delay10
djnz ide_wbsy
RET
;
; Wait for the drive to be ready to command/control.
; Returns the drive's status in Acc. if Z at exit => error(timeout), NZ=OK
;
ide_wait_ready:
ld b, 0 ; rdy_repeat=256
ide_wrdy:
IF IDEPRO
in a,(PRO_STAT)
ELSE
ld a, ide_status ; wait for RDY bit to be set
call ide_rd_8
ENDIF
and 01000000b
jr nz, ide_wait_not_busy
call delay10 ; dirt A, de:=0
djnz ide_wrdy
ret ; z = FAIL
;
; Read byte from IDE register
; input a = ide regsiter address
; output a = byte readed from ide drive
;
; bc, hl - not used
;
IF IDEPRO
ELSE
ide_rd_8:
ex de, hl
@@P5: ld hl, ide_8255_ctl
ld (hl), a ; drive address onto control lines
or ide_rd_line
ld (hl), a ; assert read pin
@@P6: ld a, (ide_8255_lsb) ; read the lower byte
ld (hl), 0 ; deassert all control pins
ex de, hl
ret
ENDIF
;
delay10:
@@55: ld de, intinchl
delayx: dec de ; 6
ld a, d ; 4
or e ; 4
ret z ; 5
jr delayx ; 12 total=31 tstates
;
; Wait for the drive to be ready to transfer data.
; Returns the drive's status in Acc. if Z at exit => error(timeout), NZ=OK
;
ide_wait_drq:
ld b, 0 ; rdy_repeat=256
ide_wdrq:
IF IDEPRO
in a,(PRO_STAT)
ELSE
ld a, ide_status ; wait for DRQ bit to be set
call ide_rd_8
ENDIF
ld c, a
and 10000000b
jr nz, ide_wdrq1 ; wait for BSY to be clear
ld a, c
and 00001000b ; wait for DRQ to be set
ret nz
ide_wdrq1:
call delay10
djnz ide_wdrq
ld a, c
ret ; z = FAIL
;
; Load position registers (sector number in LBA notation)
; (Input: HL=DriveInfo_array+8, d: 0=master, 10h=slave)
;
wr_lba: ld a, 10h
and d ; 0=master, 10h=slave. Mask out other values
or 0E0h ; 11100000b - LBA mode, Master, head 0
or (hl) ; lba+3
IF IDEPRO
out (PRO_HEAD),a
dec hl
ld a,(hl)
out (PRO_CYL_MSB),a
dec hl
ld a,(hl)
out (PRO_CYL_LSB),a
dec hl
ld a,(hl)
out (PRO_SECTOR),a
ld a,1
out (PRO_SEC_CNT),a
ret
ELSE
ld e, a
ld a, ide_head
call ide_wr_8
dec hl
ld a, ide_cyl_msb
ld e, (hl) ; lba+2
call ide_wr_8
ld a, ide_cyl_lsb
dec hl
ld e, (hl) ; lba+1
call ide_wr_8
ld a, ide_sector
dec hl
ld e, (hl) ; lba+0
call ide_wr_8
ld a, ide_sec_cnt
ld e, 1
;
; Write byte to IDE register
; input a = ide regsiter address
; e = byte to write to ide drive
; hl - not used
;
ide_wr_8:
ld c, a ; address in c
ld a, wr_ide_8255
@@P10: ld (ide_8255_cfg), a ; config 8255 chip, write mode
ld a, e
@@P11: ld (ide_8255_lsb), a ; drive lower lines with lsb (r2)
ld a, c
ex de, hl
@@P12: ld hl, ide_8255_ctl
ld (hl), a ; drive address onto control lines
or ide_wr_line
ld (hl), a ; assert write pin
ld a, rd_ide_8255 ; delay 7 tstates 7+7=14= 3 mks
ld (hl), c ; delay 7 tstates. deassert write pin
ex de, hl
@@P13: ld (ide_8255_cfg), a ; config 8255 chip, read mode
ret
ENDIF
;