-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathHALBL.280
576 lines (492 loc) · 15.8 KB
/
HALBL.280
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
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
title 'Pseudo-Disk I/O Module of CP/M-3 BIOS'
.z280
.xlist
maclib Z280EQU
maclib CPU280
maclib OPTIONS
.list
; 950314 Tilmann Reh
; 10-July-2017 Tony Nicholson
; Comments translated from German to English (using Google
; Translate with some appropriate language adjustments resulting
; from an examination of the instruction sequences). Also
; corrected the syntax to be compatible with Hector Peraza's
; ZSM4 Z80/Z180/Z280 assembler
; Driver for Pseudo-Drives. An MDrive is supported in the CPU280-RAM
; (using the total memory size minus 256k System memory) as drive E:,
; A circuit board 1MB-RAM-Disk of any capacity as drive F:, and one
; circuit board Solid-State-Disk (with EPROM or SRAM equipment) of any
; capacity as drive G:. On the circuit cards the memory expansion
; is recognised by the user jumper and adapted to the DPB accordingly.
spezial equ false ; Option: Special conversion c't Solid-State 768k
dseg ; banked
;***********************************************************************
;** Control of MDrive (internal onboard RAM) **
;***********************************************************************
; Organisation of MDrive: 256 Sectors per Track (i.e. 32k per Track),
; The number of tracks depends on the memory configuration - 8 (512k),
; 24 (1M), 56 (2M), 120 (4M).
; Initialisation: Determine the RAM size (NVRAM) and set the capacity
; for the MDrive. Output a message once this is determined.
; If in the loader: Check the Directory, initialse entries if necessary.
; Doesn't need to be setup because the MDrive is always the first drive.
MDrIni: iopage BoardP
in a,(s$Mem) ; Memory capacity: 512k-Blocks
ld h,a ; *256 = number of 2k-Blocks (if L=0)
dec h
ld l,7Fh ; Subtract 128 for System, DSM is value-1
ld (DPBE+5),hl ; Save DSM
cp 1 ; (HL = 127/383/895/1919 = 7F/17F/37F/77F)
jr nz,MDrIn1
ld (DPBE+4),a ; 256k MDrive: EXM = 1 (0 Default, from 768k)
MDrIn1: cp 5
jr nc,MDrIn3 ; about 2M RAM: DPBE already correct
ld bc,255 ; DRM with 256 entries
ld de,00F0h ; ALV with 256 entries
cp 3
jr c,MDrIn2 ; to 1M: use these values
ld e,c ; over 1M: ALV = 00FFh
inc b ; DRM = 511
MDrIn2: ld (DPBE+7),bc
ld (DPBE+9),de ; use DRM and ALV in DPB
MDrIn3:
if loader
jp DirIni ; Loader: possibly init Directory, then End!
else
inc hl
add hl,hl ; Capacity in KB
push hl
ld hl,MDrSgn
PrtSiz: call PMsg ; Output message
pop hl ; Capacity in KB
call SizOut ; Output the size
ld hl,CRLF
jp PMsg ; End by outputting a newline
endif
; GETADR calculates the physical address of the sector to be processed.
; Bit 21 20 19 18 17 16, 15 14 13 12 11 10 09 08, 07 06 05 04 03 02 01 00
; Inh. T T T T T T, T S S S S S S S, S x x x x x x x
; Add 840000h to address (beginning of MDrive is after 256k System area).
; Address transfer in AHL (24 Bit).
GetAdr: ld a,(Track)
srl a
ld b,a ; Track /2 will result in 'Bank' later
ld a,(Sector)
rra ; sector/2 = Page (CY still from Track-Bit 0)
ld l,0
rr l ; Insert in Low-Adr. -> 0 or 80h
ld h,a ; in HL phys. Address
ld a,b ; in A phys. Bank
add a,84h ; phys. Bank of MDrive start
ret
MDrRd: call GetAdr ; Phys. Address (Source)
ld (Source),hl
ld (Source+2),a
call ClcDMA ; phys. destination address (AHL)
ld (Dest),hl
ld (Dest+2),a
jr MDrSet ; Start DMA and RET
MDrWr: call GetAdr ; phys. Address (Destination)
ld (Dest),hl
ld (Dest+2),a
call ClcDMA ; phys. source address (AHL)
ld (Source),hl
ld (Source+2),a
; Insert descriptor into DMA Parameter block, start DMA and end.
; This entrypoint and the DMA-PB are also used by other drivers.
MDrSet: ld hl,1000000100000000b ; Descriptor: Mem --> Mem, Bytes Cont.
XDrSet: ld (Dscrpt),hl
ld hl,Xfer
call DmaSet ; DMA 3 init --> transfer
iopage BusP ; switch back to Bus-Page
xor a ; no errors
ret
Xfer: defb dal3 ; DMA 3
Dest: defs 3
Source: defs 3
defw 128 ; Length: 128 Byte (all Pseudo-Drives)
Dscrpt: defs 2
if loader
if deutsch
MDrQry: defz cr,lf,'MDrive l|schen ? '
endif
if english
MDrQry: defz cr,lf,'Erase MDrive ? '
endif
MDrLbl: defb 20h,'MDRIVE ',31h,0,0,0
defw 0,0,0,0,Date,0,Date,0
else
MDrSgn: defz 'E: MDrive '
CRLF: defz cr,lf
endif
; Extended Disk Parameter Header & Allocation Vectors:
DPHE:: defw 0,0,0,0,0,0
defw DPBE,0
if loader
defw 0,BCB,-1,-1
else
defw ALVE,-2,-1,-2
endif
defb 0
defw MDrIni,0,MDrRd,MDrWr ; Driver entry points
EBlks equ 1920 ; Maximum (with 4M memory expansion)!
if not loader
ALVE: defs (EBlks+7)/4 ; Allocation Vector (2 Bit)
endif
cseg ; DPB must be resident
DPBE: defw 256 ; 128 byte sec/trk
defb 4,15 ; block shift, mask (2k)
defb 0 ; extent mask
defw EBlks-1 ; max block number
defw 1023 ; dir entries
defb 0FFh,0FFh ; dir blocks alloc vec
defw 8000h ; checksum size
defw 0 ; tracks offset
defb 0,0 ; phys sec shift
dseg
;***********************************************************************
;** Control of the c't-1-MB-RAM-Disk **
;***********************************************************************
if ctram
; Definition of I/O addresses
ctrBase equ 5Ch ; Base address
ctrDat equ ctrBase ; Data register RAM-Floppy
ctrSec equ ctrBase+1 ; Sector register RAM-Floppy
ctrTrk equ ctrBase+2 ; Track register RAM-Floppy
ctrSta equ ctrBase+3 ; Status register RAM-Floppy
; Initialisation: Determine the RAM size (Jumper) and size the RAM
; disk capacity. Output message to confirm device. In case of error
; delete drive table entry and report accordingly.
ctrIni: iopage BusP
in a,(ctrSta) ; RAM-Disk F: check for existence
inc a
jr z,KillF ; not there: Delete entry and output message
and 0C0h ; Size detection bits
rlca
rlca ; push to the far right
inc a ; possible: 1..4 Banks installed
ld h,a
ld l,0 ; to HL as 256..1024
srl h
rr l ; halved: 128..512 = number of 2k-Groups
dec hl
ld (DPBF+5),hl ; save DSM to DPB
bit 0,h ; (HL = 127/255/383/511 = 7F/FF/17F/1FF)
jr nz,ctrIn1
ld (DPBF+4),1 ; <= 512k : insert EXM = 1 (0 Default)
ctrIn1:
if loader
ld hl,ctrAdr
ld de,DrvRd
ld bc,8
ldir ; copy routine addresses for DirIni
jp DirIni ; Loader: possibly init Directory and end!
ctrAdr: defw ctrRd,ctrWr,ctrLbl,ctrQry ; Routine addresses for RAM-Disk
else
inc hl
add hl,hl ; Capacity in KB
push hl ; on Stack
ld hl,ctrSgn
jp PrtSiz ; Output message and capacity
endif
KillF: ld hl,0
ld (DTbl+10),hl ; Delete entry from DPHF
if loader
ret
else
ld hl,ctrBad
jp PMsg ; Print controller bad and end
endif
; c't RAM Floppy: Sector and Track registers are reversed so AutoSize
; needs to change the DSM (due to Bank Select by "Sector" register).
ctrRd: iopage BusP ; external cards on ECB-Bus
ld a,(Sector)
out (ctrTrk),a ; set Sector register
ld a,(Track)
out (ctrSec),a ; set Track register
ld hl,ctrDat
ld (Source),hl ; RAM-Floppy-Data port as source
jp ctRd ; DMA for ECB-Read prog., End
ctrWr: iopage BusP ; external cards on ECB-Bus
in a,(ctrSta) ; Statusport RAM-Disk
and 2
ret nz ; WRITE-PROTECTED, Error-Code 2
ld a,(Sector)
out (ctrTrk),a ; set Sector register
ld a,(Track)
out (ctrSec),a ; set Track register
ld hl,ctrDat
ld (Dest),hl ; RAM-Floppy-Date port as destination
jp ctWr ; DMA for ECB-Write prog., End
if loader
if deutsch
ctrQry: defz cr,lf,'RAM-Disk l|schen ? '
endif
if english
ctrQry: defz cr,lf,'Erase RAM-Disk ? '
endif
ctrLbl: defb 20h,'RAM-DISK ',31h,0,0,0
defw 0,0,0,0,Date,0,Date,0
else
ctrSgn: defz 'F: RAM-Disk '
if deutsch
ctrBad: defz 'Fehler: RAM-Disk nicht installiert',cr,lf
endif
if english
ctrBad: defz 'Error: RAM-Disk not installed',cr,lf
endif
endif
; Extended Disk Parameter Header & Allocation Vectors:
DPHF:: defw 0,0,0,0,0,0
defw DPBF,0
if loader
defw 0,BCB,-1,-1
else
defw ALVF,-2,-1,-2
endif
defb 0
defw ctrIni,0,ctrRd,ctrWr ; Driver entry points
FBlks equ 512 ; Maximum 512 Blocks = 1 MB
if not loader
ALVF: defs (FBlks+7)/4 ; Allocation Vector (2 Bit)
endif
cseg
DPBF: defw 256 ; 128 byte sec/trk
defb 4,15 ; block shift, mask (2k)
defb 0 ; extent mask
defw FBlks-1 ; max block number
defw 191 ; dir entries
defb 0E0h,0 ; dir blocks alloc vec
defw 8000h ; checksum size
defw 0 ; tracks offset
defb 0,0 ; phys sec shift
dseg
endif ; (ctram)
;***********************************************************************
;** Controlling the c't-Solid-State-Disk **
;***********************************************************************
if ctsolid
; Address definitions
ctsBase equ 54h ; Base address
ctsSec equ ctsBase ; Sector register Solid-State-Floppy
ctsRdD equ ctsBase ; Read Data register Solid-State-Floppy
ctsTrk equ ctsBase+1 ; Track register Solid-State-Floppy
ctsSta equ ctsBase+1 ; Status register Solid-State-Floppy
ctsWrD equ ctsBase+2 ; Write Data register Solid-State-Floppy
; Initialisation: Determin the RAM size (Jumper) and capacity.
; Output a message if configured. If no device found or an error
; occurs, delete the drive entry and report accordingly.
; A conversion to 768k (3 Banks each 256k) is supported as an option.
; In this case, both capacity jumpers must be left open.
ctsIni: iopage BusP
in a,(ctsSta) ; Solid-State-Disk G: check for existence
inc a ; 0/1/2/3 --> 1/2/3/0 in lower Bits
jr z,KillG ; If not there (read FFh): delete
and 3 ; Size detection Bits +1 (64k,128k,256k)
if spezial
jr z,cts768 ; both original Bits 1: Special conversion 768k
else
jr z,KillG ; both original-Bits 1 not supported: delete
endif
cp 3
sbc a,-1 ; --> 1,2,4
multu a,64 ; --> 64,128,256
if loader
dec hl
ld (DPBG+5),hl ; set DSM into DPB
ret
else
push hl ; save capacity in KB on Stack
dec hl
ld (DPBG+5),hl ; use DSM in DPB
ld hl,ctsSgn
jp PrtSiz ; Output message and capacity
endif
if spezial
cts768: ldw (DPBG+2),0F04h ; BSH and BLM: 2k-Blocks
ldw (DPBG+5),383 ; 768k are 384 Blocks
ld (DPBG+7),127 ; now 128 DIR entries (also 2 Blocks)
if loader
ret
else
push 768
ld hl,ctsSgn
jp PrtSiz ; Output message and capacity
endif
endif
KillG: ld hl,0
ld (DTbl+12),hl ; Disable entry in DPHG
if loader
ret
else
ld hl,ctsBad
jp PMsg ; Error message and end
endif
; Reading of Solid-State-Floppy always possible (RAM or EPROM).
ctsRd: iopage busp ; external cards on ECB-Bus
ld a,(Track)
out (ctsTrk),a ; set track register
ld a,(Sector)
out (ctsSec),a ; set sector register
ld hl,ctsRdD
ld (Source),hl ; EPROM-Floppy-Data port as source
endif ; (ctsolid)
if ctram or ctsolid ; common Routine
ctRd: xor a
ld (Source+2),a ; I/O-Page 00 for ECB-Bus
call ClcDMA ; Phys. calculate destination address
ld (Dest),hl
ld (Dest+2),a ; insert into DMA Table
ld hl,1110000100000000b ; Descriptor: I/O --> MEM, Bytes Cont.
jp XDrSet ; set DMA/Enable, RETURN
endif ; (common Routine)
if ctsolid and not loader
; Writing to Solid-State-Floppy only possible with RAM
ctsWr: iopage busp ; external cards on ECB-Bus
in a,(ctsSta) ; read status port
rrca ; push bit to the right
and 2
ret nz ; EPROM equipment: WRPROT
ld a,(Track)
out (ctsTrk),a ; set track register
ld a,(Sector)
out (ctsSec),a ; set sector register
ld hl,ctsWrD
ld (Dest),hl ; RAM-Floppy-Data port as source
endif ; (ctsolid)
if ctram or ctsolid ; Common Routine
ctWr: xor a
ld (Dest+2),a ; I/O-Page 00 for ECB-Bus
call ClcDMA ; Phys. Calculate source address
ld (Source),hl
ld (Source+2),a ; insert it into DMA Table
ld hl,1000000100001100b ; Descriptor: MEM --> I/O, Bytes Cont.
jp XDrSet ; set DMA /Enable, RETURN
endif ; (Common Routine)
if ctsolid
iff loader
ctsSgn: defz 'G: Solid-State-Disk '
if deutsch
ctsBad: defz 'Fehler: Solid-State-Disk nicht installiert',cr,lf
endif
if english
ctsBad: defz 'Error: Solid-State-Disk not installed',cr,lf
endif
endif
; Extended Disk Parameter Header & Allocation Vectors:
DPHG:: defw 0,0,0,0,0,0
defw DPBG,0
if loader
defw 0,BCB,-1,-1
defb 0
defw ctsIni,0,ctsRd,0 ; Driver entry points
else
defw ALVG,-2,-1,-2
defb 0
defw ctsIni,0,ctsRd,ctsWr ; Driver entry points
endif
if spezial
GBlks equ 384
else
GBlks equ 256
endif
if not loader
ALVG: defs (GBlks+7)/4 ; Allocation Vector (2 Bit)
endif
; DPBG is designed for 256k EPROM/SRAM assembly.
; (patched for special 768k conversion at installation)
cseg ; DPB must be resident
DPBG: defw 256 ; 128 byte sec/trk
defb 3,7 ; block shift, mask (1k)
defb 0 ; extent mask
defw GBlks-1 ; max block number
defw 63 ; dir entries
defb 0C0h,0 ; dir blocks alloc vec
defw 8000h ; checksum size
defw 0 ; tracks offset
defb 0,0 ; phys sec shift
dseg
endif ; (ctsolid)
;***********************************************************************
;** Initialisation of RAM Floppies (only in the loader) **
;***********************************************************************
; General initialisation routine for RAM Disks. First the first sector
; in it and the first diectory entry (drive label) is examined. If
; the label if intact nothing is done. If not found, query user about
; re-initialising the directory. It is assumed all the directory is on
; a single track on the logical drive (256 sectors = 1024 entries).
; The addresses DrvRd, DrvWr, DrvLbl und DrvQry must already be set in
; the extended parameter block.
if loader ; only needed in the loader
DirIni: ld hl,0
ld (Track),hl
ld (Sector),hl ; Track and Sector 0
ldw (DMA),Buffer ; Destination address: Scratch-Buffer
ld hl,(DrvRd)
call (hl) ; read first sector
ld hl,(DrvLbl)
ld de,Buffer
call ChkLbl ; Check Directory Label
ret z ; Label unchanged: do not erase --> End
ld hl,(DrvQry)
call nc,Query ; a few mistakes: Prompt to erase
ret nc ; do not erase: End
DirIni1:ld hl,Buffer
ld de,Buffer+1
ld bc,7Fh
ld (hl),0E5h
ldir ; fill sector with E5h
ld (Buffer+60h),21h ; Prepare 1x SFCB
ld b,0 ; Counter for 256 Sectors (1024 entries)
DirIni2:push bc
ld a,b
dec a ; Sector number 255..0
jr nz,DirIni3
ld hl,(DrvLbl) ; in sector 0 Directory Label
ld de,Buffer
ld bc,20h
ldir ; Copy Directory Label to Buffer
DirIni3:ld (Sector),a
ld hl,(DrvWr)
call (hl) ; Write Sector (addresses still valid)
pop bc ; counter
cp a,2
ret z ; Write-Protected: Cancel!
djnz DirIni2 ; Erase entire directory
ret ; then done!
; Check the Directory Label from (HL) for compliance with (DE).
; Exact match Z, up to 5 errors NC, with more errors C.
ChkLbl: ld bc,2005h ; Length of Label entry (B), error counter (C)
ChkLbl1:ld a,(de)
cp (hl) ; compare bytes
jr z,ChkLbl2
dec c ; different: counter -1
ChkLbl2:inc hl
inc de ; Pointer +1
djnz ChkLbl1 ; check entire volume label
ld a,c
cp 5
ret z ; C unchanged: exact match, so Z
rlca
ret ; set at more than 5 errors CY, NZ
; Prompt to erase question (HL) and wait for response (J/N/Y).
; For answer 'N' CY=0, otherwise CY=1.
Query: call PMsg ; Output question
Query1: call ConIn ; Wait for character input
and 5Fh ; CAPS
cp YesChar
scf
jr z,Query2
cp NoChar
jr nz,Query1 ; Ignore other responses
Query2: push af ; save CY
call COA ; Echo character
pop af
ret
; Variables only used for initialisation (Loader):
DrvRd: defw MDrRd ; Driver entry for Read
DrvWr: defw MDrWr ; Driver entry for Write
DrvLbl: defw MDrLbl ; Address of correct volume label
DrvQry: defw MDrQry ; Address of the enquiry
endif ; (loader)
end