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