]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blob - cbios/ldrbios.180
Add ldrbios.180 and generate cpmldr.com Load cpm3.sys from CF-IF device.
[z180-stamp-cpm3.git] / cbios / ldrbios.180
1 title 'LDRBIOS for CP/M 3.0'
2
3 ; Port Address Equates
4
5 include config.inc
6 include z180reg.inc
7
8
9 ; IDE Task File Register Definitions
10
11 IDEDat equ IDEBASE+0 ; Data Register
12 IDEErr equ IDEBASE+1 ; Error Register
13 IDEFeat equ IDEBASE+1 ; Feature Register
14 IDESCnt equ IDEBASE+2 ; Sector Count
15 IDESNum equ IDEBASE+3 ; Sector Number
16 IDECLo equ IDEBASE+4 ; Cylinder Low
17 IDECHi equ IDEBASE+5 ; Cylinder High
18 IDESDH equ IDEBASE+6 ; Drive and Head
19 IDECmd equ IDEBASE+7 ; Command / Status
20
21 ; IDE Hard disk commands:
22
23 CmdHome equ 10h ; Recalibrate
24 CmdRd equ 20h ; Read Sector
25 CmdWr equ 30h ; Write Sector
26 CmdInit equ 91h ; Initialize Drive Params
27 CmdId equ 0ECh ; Read ID
28 CmdSF equ 0EFh ; Set Feature
29
30 ; Partition Table Structures
31
32 PART_TYPE equ 4
33 PART_START equ 8
34 PART_SIZE equ 12
35
36 ; Partition table id
37 ; (see http://www.win.tue.nl/~aeb/partitions/partition_types-1.html)
38
39 PARTID1_FAT16 equ 00EH
40 PARTID2_FAT16 equ 006H
41 PARTID_CPM equ 052H
42
43
44 TIMEOUT equ 1000
45
46 cr equ 13
47 lf equ 10
48
49
50 .z80
51 cseg
52
53 ; BIOS Jump vector.
54
55 ?boot: jp boot ; initial entry on cold start
56 ?wboot: jp wboot ; reentry on program exit, warm start
57
58 ?const: jp const ; return console input status
59 ?conin: jp conin ; return console input character
60 ?cono: jp conout ; send console output character
61 ?list: jp list ; send list output character
62 ?auxo: jp auxout ; send auxilliary output character
63 ?auxi: jp auxin ; return auxilliary input character
64
65 ?home: jp home ; set disks to logical home
66 ?sldsk: jp seldsk ; select disk drive, return disk parameter info
67 ?sttrk: jp settrk ; set disk track
68 ?stsec: jp setsec ; set disk sector
69 ?stdma: jp setdma ; set disk I/O memory address
70 ?read: jp read ; read physical block(s)
71 ?write: jp write ; write physical block(s)
72
73 ?lists: jp listst ; return list device status
74 ?sctrn: jp sectrn ; translate logical to physical sector
75
76 ?conos: jp conost ; return console output status
77 ?auxis: jp auxist ; return aux input status
78 ?auxos: jp auxost ; return aux output status
79 ?dvtbl: jp devtbl ; return address of device def table
80 ?devin: jp cinit ; change baud rate of device
81
82 ?drtbl: jp getdrv ; return address of disk drive table
83 ?mltio: jp multio ; set multiple record count for disk I/O
84 ?flush: jp flush ; flush BIOS maintained disk caching
85
86 ?mov: jp move ; block move memory to memory
87 ?tim: jp time ; Signal Time and Date operation
88 ?bnksl: jp bnksel ; select bank for code execution and default DMA
89 ?stbnk: jp setbnk ; select different bank for disk I/O DMA operations.
90 ?xmov: jp xmove ; set source and destination banks for one operation
91
92 jp 0 ; reserved for future expansion
93 jp 0 ; reserved for future expansion
94 jp 0 ; reserved for future expansion
95
96 ;----------------------------------------------------------------------
97
98 hwini_tab:
99 db (hwini0_e-$)/2 ;count
100 db rcr,CREFSH ;configure DRAM refresh
101 db dcntl,CWAITIO ;wait states
102 db ccr,M_NCD ;No Clock Divide
103 db cmr,PHI_X2 ;X2 Clock Multiplier
104 db omcr,~M_IOC ;Operation Mode Control Register
105 ;MMU
106 db cbr,SYS$CBR ;Common Base Register
107 db cbar,USR$CBAR ;Common Base Area Register
108 ;ASCI0
109 db asext1,0 ;disable BRG
110 db stat1,00000000b ;disable RX, TX interrupt, disable CTS1
111 db cntlb1,10000000b;PS:10 DR:16 Rate:1 --> BR = Phi/160
112 db cntla1,01100101b;RE TE RTS:0 8N2
113 hwini0_e:
114 db 0 ;stop mark
115 db 0,0,0,0,0,0,0,0 ;
116
117 msg_boot:
118 db cr,lf,'CPMLDR error: Unable to locate CP/M partition',cr,lf,0
119
120 ;-------------------------------------------------------------------------------
121
122 ; CP/M 3 Disk definition macros
123
124 maclib cpm3slr.lib ; dpb mcaro
125
126 ; The dph macro from the lib depends on GENCPM
127
128 dphldr macro ?trans,?dpb,?csize,?asize,?dirbcb,?dtabcb
129 local ?csv,?alv
130 dw ?trans ; translate table address
131 db 0,0,0,0,0,0,0,0,0 ; BDOS Scratch area
132 db 0 ; media flag
133 dw ?dpb ; disk parameter block
134 if nul ?csize
135 dw 0 ; permanently mounted, no checksum vector
136 else
137 if ?csize = 0
138 dw 0
139 else
140 dw ?csv ; checksum vector
141 endif
142 endif
143 if nul ?asize
144 dw 0 ; no alloc vector
145 else
146 if ?asize = 0
147 dw 0
148 else
149 dw ?alv ; allocation vector
150 endif
151 endif
152 dw ?dirbcb
153 dw ?dtabcb
154 dw 0ffffh ; no hash
155 db 0 ; hash bank
156 if not nul ?csize
157 if ?csize <> 0
158 ?csv ds ?csize ; checksum vector
159 endif
160 endif
161 if not nul ?asize
162 if ?asize <> 0
163 ?alv ds ?asize ; allocation vector
164 endif
165 endif
166 endm
167
168 ;-------------------------------------------------------------------------------
169
170 ; dphldr translate$table, - disk parameter header
171 ; disk$parameter$block,
172 ; checksum$size, (optional)
173 ; alloc$size (optional)
174 ; dir$bcb
175 ; data$bcb
176 dph0:
177 dphldr 0,dpbsimhd512,0,0,bcb,bcb
178
179 bcb:
180 db 0ffh
181 rept 9
182 db 0
183 endm
184 dw buffer
185
186 ; dpb physical$sector$size, - disk parameter block
187 ; physical$sectors$per$track,
188 ; number$tracks,
189 ; block$size,
190 ; number$dir$entries,
191 ; track$offset,
192 ; checksum$vec$size (optional)
193
194 dpbsimhd512:
195 dpb 512,8,2048,4096,1024,6,8000h
196
197 ;-------------------------------------------------------------------------------
198
199 wboot: ; jump vector locations not used
200 const:
201 conin:
202 list:
203 auxout:
204 auxin:
205 write:
206 listst:
207 conost:
208 auxist:
209 auxost:
210 devtbl:
211 cinit:
212 getdrv:
213 multio:
214 flush:
215 time:
216 bnksel:
217 setbnk:
218 xmove:
219 ret
220
221 ;-------------------------------------------------------------------------------
222 ; output bytes to ports
223 ;
224 ; hl: tables of port,value pairs:
225 ; db n, port1,val1, port2,val2,... portn,valn
226 ; ...
227 ; db 0 ; Terminate table
228
229 ioini1l:
230 push bc
231 jr io1_nxt
232 io1_lp:
233 ld c,(hl) ;port address
234 inc hl
235 otim
236 jr nz,io1_lp
237 io1_nxt:
238 ld b,(hl) ;count
239 inc hl
240 inc b
241 djnz io1_lp
242
243 pop bc
244 ret
245
246 ;-------------------------------------------------------------------------------
247 ; print message @<HL> up to a null
248
249 ?pmsg:
250 ld a,(hl)
251 or a
252 ret z
253 ld c,a
254 push hl
255 call ?cono
256 pop hl
257 inc hl
258 jr ?pmsg
259
260 ;-------------------------------------------------------------------------------
261
262 boot:
263 ; Init CPU, MMU, ASCI0
264
265 ld hl,hwini_tab
266 call ioini1l
267
268 ; Init disk partition
269
270 call read_parttbl
271 or a
272 jr nz,boot_err
273
274 ; check_signature
275
276 ld hl,buffer+512-1
277 ld a,0aah
278 cp (hl) ; Test, if it has a valid MBR
279 jr nz,boot_err
280 dec hl
281 cpl ; a=055h
282 cp (hl) ;
283 jr nz,boot_err
284
285 ; Find CP/M paartition
286 ; Look for first CP/M partition and save partition offset
287
288 ld hl,buffer+512-2-64+PART_TYPE ; Point to partition type of first first partition table entry
289 ld de,16
290 ld b,4 ; Max # of partition table entries
291 ploop:
292 ld a,PARTID_CPM
293 sub (HL) ; Test for CP/M Partition
294 jr nz,pnext
295 ld bc,4
296 add hl,bc ; Point to partition start (lba)
297 ld de,ptab_start
298 ldir
299 ret ;a=0
300
301 pnext:
302 add hl,de
303 djnz ploop
304
305 boot_err:
306 ld hl,msg_boot
307 call ?pmsg
308 halt_loop:
309 halt
310 jr halt_loop
311
312 ;-------------------------------------------------------------------------------
313
314 conout:
315 in0 a,(stat1)
316 and M_TDRE
317 jr z,conout
318 out0 (tdr1),c
319 ld a,c
320 ret
321
322 ;-------------------------------------------------------------------------------
323
324 move:
325 ex de,hl ; we are passed source in DE and dest in HL
326 ldir ; use Z80 block move instruction
327 ex de,hl ; need next addresses in same regs
328 ret
329
330 ;-------------------------------------------------------------------------------
331 ; Select Disk Drive.
332 ; Return address of disk parameter header in <HL>
333
334 seldsk:
335 ld hl,dph0
336 ret
337
338 ; Home selected drive. Treated as SETTRK(0).
339
340 home:
341 ld bc,0 ; same as set track zero
342
343 ; Set Track. Saves track address from <BC> in @trk.
344
345 settrk:
346 ld (@trk),bc
347 ret
348
349 ; Set Sector. Saves sector number from <BC> in @sect.
350
351 setsec:
352 ld (@sect),bc
353 ret
354
355 ; Set Disk Memory Address. Saves DMA address from <BC> in @dma.
356
357 setdma:
358 ld (@dma),bc
359 ret
360
361 ; Translate sector address. Not needed. Return physical=logical.
362
363 sectrn:
364 ld l,c
365 ld h,b
366 ret
367
368 ;-----------------------------------------------------------------
369
370 chk_to:
371 xor a ;
372 to_l:
373 dec a
374 jr nz,to_l ;
375 dec hl ; 4
376 ld a,h ; 4
377 or l ; 4
378 ret nz ; 10/5
379 ccf ; 3
380 ret ; 9
381
382 ;-------------------------------------------------------------------------------
383 ; Wait for ready signal with time out
384 ; return:
385 ; a = 0 if ok
386 ; a = ff if timeout
387
388 wait_rdy_to:
389 push hl
390 ld hl,TIMEOUT
391 wrdy_l:
392 in a,(IdeCmd)
393 xor 01000000b
394 and 11000000b ; clears carry
395 jr z,wrdy_e
396 call chk_to
397 jr nc,wrdy_l
398 wrdy_e:
399 pop hl
400 sbc a,a
401 ret
402
403
404 ;-------------------------------------------------------------------------------
405
406 do_ide_cmd:
407 out (IdeCmd),a ;
408 call wait_rdy_to
409 ret c
410 in a,(IdeCmd)
411 and 10001001b ;
412 ret
413
414
415 ;-------------------------------------------------------------------------------
416 ; Read partition table
417
418 read_parttbl:
419 ld hl,ptab_start
420 ld b,8
421 rp_l:
422 ld (hl),0
423 inc hl
424 djnz rp_l
425
426 ld hl,buffer
427 ld (@dma),hl
428
429 ; fall thru
430
431 ;-------------------------------------------------------------------------------
432 ; Read a sector
433
434 ; compute logical block number (lba) --> cf-controller
435
436 ; TODO: sectors per track from dpb
437 ; lba = track * 8 + sector
438
439 read:
440 ld iy,ptab_start
441 xor a
442 ld hl,(@trk)
443 add hl,hl
444 adc a,a ; *2
445 add hl,hl
446 adc a,a ; *4
447 add hl,hl
448 adc a,a ; *8
449 ld de,(@sect)
450 add hl,de
451 adc a,0
452 ld e,a
453 call wait_rdy_to
454 ld a,(iy+0) ; add partition start
455 add a,l
456 out (IdeSNum),a
457 ld a,(iy+1)
458 adc a,h
459 out (IdeCLo),a
460 ld a,(iy+2)
461 adc a,e
462 out (IdeCHi),a
463 ld a,(iy+3)
464 adc a,0
465 and 00FH
466 or 0E0H
467 out (IdeSDH),a
468 ld hl,(@dma)
469
470 ld a,1 ; number of sectors to read
471 out (IdeSCnt),a ; set sector count
472
473 ld a,CmdRd
474 out (IdeCmd),a ; command: read sector data
475 ld bc,IdeDat ; I/O address
476 wdrq:
477 in a,(IdeCmd) ; wait for DRQ to become active
478 bit 3,a
479 jr z,wdrq
480 inir ; read 512 data bytes (2 x 256)
481 inir
482 wnb: ; wait while busy
483 in a,(IdeCmd) ;
484 rlca
485 jr c,wnb
486 rrca ; restore status
487 and 10001001b ; Busy, DRQ, or Error?
488 ret z ; return 0, if everything is ok
489 ld a,1
490 ret
491
492 ;-------------------------------------------------------------------------------
493
494 ptab_start:
495 dw 0,0
496 @trk: dw 0
497 @sect: dw 0
498 @dma: dw 0
499
500 buffer:
501 end