]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blame_incremental - cbios/bioskrnl.180
Extended drive table for use with DRIVE.COM, a dynamic drive re-assignment utility.
[z180-stamp-cpm3.git] / cbios / bioskrnl.180
... / ...
CommitLineData
1 title 'Root module of relocatable BIOS for CP/M 3.0'\r
2\r
3 ; version 1.0 15 Sept 82\r
4\r
5 maclib z180reg.inc\r
6 maclib config.inc\r
7\r
8\r
9; Copyright (C), 1982\r
10; Digital Research, Inc\r
11; P.O. Box 579\r
12; Pacific Grove, CA 93950\r
13\r
14\r
15; This is the invariant portion of the modular BIOS and is\r
16; distributed as source for informational purposes only.\r
17; All desired modifications should be performed by\r
18; adding or changing externally defined modules.\r
19; This allows producing "standard" I/O modules that\r
20; can be combined to support a particular system\r
21; configuration.\r
22\r
23ctlQ equ 'Q'-'@'\r
24ctlS equ 'S'-'@'\r
25\r
26ccp equ 0100h ; Console Command Processor gets loaded\r
27 ; into the TPA\r
28\r
29 cseg ; GENCPM puts CSEG stuff in common memory\r
30\r
31\r
32 ; variables in system data page\r
33\r
34 extrn @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors\r
35 extrn @mxtpa ; addr of system entry point\r
36 extrn @bnkbf ; 128 byte scratch buffer\r
37\r
38 ; initialization\r
39\r
40 extrn hwinit,?init ; general initialization and signon\r
41 extrn ?ldccp,?rlccp ; load & reload CCP for BOOT & WBOOT\r
42\r
43 ; user defined character I/O routines\r
44\r
45 extrn ?ci,?co,?cist,?cost ; each take device in <B>\r
46 extrn ?cinit ; (re)initialize device in <C>\r
47 extrn ioctl\r
48 extrn @ctbl ; physical character device table\r
49\r
50 ; disk communication data items\r
51\r
52 extrn @dtbl ; table of pointers to XDPHs\r
53 public @adrv,@rdrv,@trk,@sect ; parameters for disk I/O\r
54 public @dma,@dbnk,@cnt ; '' '' '' ''\r
55 public @xdph,@op\r
56\r
57 ; memory control\r
58\r
59 public @cbnk ; current bank\r
60 extrn ?xmove,?move ; select move bank, and block move\r
61 extrn ?bank ; select CPU bank\r
62\r
63 ; clock support\r
64\r
65 extrn ?time ; signal time operation\r
66\r
67 extrn stampf\r
68 extrn ijphl ; vectored call\r
69\r
70 maclib modebaud.inc ; define mode bits\r
71\r
72\r
73 ; External names for BIOS entry points\r
74\r
75 public ?boot,?wboot,boot,?const,?conin,?cono,?list,?auxo,?auxi\r
76 public ?home,?sldsk,?sttrk,?stsec,?stdma,?read,?write\r
77 public ?lists,?sctrn\r
78 public ?conos,?auxis,?auxos,?dvtbl,?devin,?drtbl\r
79 public ?mltio,?flush,?mov,?tim,?bnksl,?stbnk,?xmov\r
80\r
81 extrn bs$stack\r
82 extrn _b0hlcall\r
83\r
84\r
85 ; BIOS Jump vector.\r
86\r
87 ; All BIOS routines are invoked by calling these\r
88 ; entry points.\r
89\r
90?boot: jp boot ; initial entry on cold start\r
91?wboot: jp wboot ; reentry on program exit, warm start\r
92\r
93?const: jp const ; return console input status\r
94?conin: jp conin ; return console input character\r
95?cono: jp conout ; send console output character\r
96?list: jp list ; send list output character\r
97?auxo: jp auxout ; send auxiliary output character\r
98?auxi: jp auxin ; return auxiliary input character\r
99\r
100?home: jp home ; set disks to logical home\r
101?sldsk: jp seldsk ; select disk drive, return disk parameter info\r
102?sttrk: jp settrk ; set disk track\r
103?stsec: jp setsec ; set disk sector\r
104?stdma: jp setdma ; set disk I/O memory address\r
105?read: jp read ; read physical block(s)\r
106?write: jp write ; write physical block(s)\r
107\r
108?lists: jp listst ; return list device status\r
109?sctrn: jp sectrn ; translate logical to physical sector\r
110\r
111?conos: jp conost ; return console output status\r
112?auxis: jp auxist ; return aux input status\r
113?auxos: jp auxost ; return aux output status\r
114?dvtbl: jp devtbl ; return address of device def table\r
115?devin: jp ?cinit ; change baud rate of device\r
116\r
117?drtbl: jp getdrv ; return address of disk drive table\r
118?mltio: jp multio ; set multiple record count for disk I/O\r
119?flush: jp flush ; flush BIOS maintained disk caching\r
120\r
121?mov: jp ?move ; block move memory to memory\r
122?tim: jp ?time ; Signal Time and Date operation\r
123?bnksl: jp bnksel ; select bank for code execution and default DMA\r
124?stbnk: jp setbnk ; select different bank for disk I/O DMA operations\r
125?xmov: jp ?xmove ; set source and destination banks for one operation\r
126\r
127 jp stampf ; stamp system specific functions\r
128 ; reserved for system implementor\r
129 jp 0 ; reserved for future expansion\r
130 jp 0 ; reserved for future expansion\r
131?ioctl jp ioctl ;\r
132\r
133\r
134 rept 32\r
135 db '|'\r
136 endm\r
137boot$stack:\r
138\r
139\r
140 ; BOOT\r
141 ; Initial entry point for system startup.\r
142\r
143 dseg ; this part can be banked\r
144\r
145boot:\r
146 ld a,SYS$CBR\r
147 out0 (cbr),a\r
148 ld a,USR$CBAR\r
149 out0 (cbar),a\r
150 ld sp,bs$stack\r
151\r
152 call hwinit ; first time hardware initialisation\r
153\r
154 ld bc,16*256 + 0 ; initialize all 16 character devices\r
155c$init$loop:\r
156 push bc\r
157 call ?cinit\r
158 pop bc\r
159 inc c\r
160 djnz c$init$loop\r
161\r
162 call ?init ; perform any additional system initialization\r
163 ; and print signon message\r
164\r
165 ld bc,16*256+0\r
166 ld hl,@dtbl ; init all 16 logical disk drives\r
167d$init$loop:\r
168 push bc ; save remaining count and abs drive\r
169 ld e,(hl)\r
170 inc hl\r
171 ld d,(hl)\r
172 inc hl ; grab @drv entry\r
173 ld a,e\r
174 or d\r
175 jr z,d$init$next ; if null, no drive\r
176 push hl ; save @drv pointer\r
177 push de\r
178 pop ix ; XDPH address in <DE>\r
179 ld b,(ix-2)\r
180 ld (@ADRV),bc ; save absolute and relative drive code\r
181 ld l,(ix-4)\r
182 ld h,(ix-3) ; get init pointer\r
183 call ijphl ; call init routine\r
184 pop hl ; recover @drv pointer\r
185d$init$next:\r
186 pop bc ; recover counter and drive #\r
187 inc c\r
188 djnz d$init$loop ; and loop for each drive\r
189 jp boot$1\r
190\r
191 cseg ; following in resident memory\r
192\r
193boot$1:\r
194 ld sp,boot$stack\r
195 call set$jumps\r
196 call ?ldccp ; fetch CCP for first time\r
197 jp ccp\r
198\r
199\r
200 ; WBOOT\r
201 ; Entry for system restarts.\r
202\r
203wboot:\r
204 ld sp,boot$stack\r
205 call set$jumps ; initialize page zero\r
206 call ?rlccp ; reload CCP\r
207 jp ccp ; then reset jmp vectors and exit to ccp\r
208\r
209\r
210set$jumps:\r
211\r
212 if banked\r
213 ld a,1\r
214 call ?bnksl\r
215 endif\r
216\r
217 ld a,0C3h ; jp opcode\r
218 ld (0),a\r
219 ld (5),a ; set up jumps in page zero\r
220 ld hl,?wboot\r
221 ld (1),hl ; BIOS warm start entry\r
222 ld hl,(@MXTPA)\r
223 ld (6),hl ; BDOS system call entry\r
224 ret\r
225\r
226\r
227\r
228 ; DEVTBL\r
229 ; Return address of character device table\r
230\r
231devtbl:\r
232 ld hl,@ctbl\r
233 ret\r
234\r
235\r
236 ; GETDRV\r
237 ; Return address of drive table\r
238\r
239getdrv:\r
240 ld hl,@dtbl\r
241 ret\r
242\r
243\r
244\r
245 ; LIST\r
246 ; List Output. Send character in <C>\r
247 ; to all selected devices.\r
248\r
249list:\r
250 ld hl,(@lovec) ; fetch list output bit vector\r
251 jr out$scan\r
252\r
253\r
254 ; AUXOUT\r
255 ; Auxiliary Output. Send character in <C>\r
256 ; to all selected devices\r
257\r
258auxout:\r
259 ld hl,(@aovec) ; fetch aux output bit vector\r
260 jr out$scan\r
261\r
262\r
263 ; CONOUT\r
264 ; Console Output. Send character in <C>\r
265 ; to all selected devices\r
266\r
267conout:\r
268\r
269 ld hl,(@covec) ; fetch console output bit vector\r
270\r
271out$scan:\r
272 ld b,0 ; start with device 0\r
273co$next:\r
274 add hl,hl ; shift out next bit\r
275 jr nc,not$out$device\r
276 push hl ; save the vector\r
277 push bc ; save device num and the character\r
278 call ?co ; if device selected, print it\r
279 pop bc ; recover count and character\r
280 pop hl ; recover the rest of the vector\r
281not$out$device:\r
282 inc b ; next device number\r
283 ld a,h\r
284 or l ; see if any devices left\r
285 jr nz,co$next ; and go find them...\r
286 ret\r
287\r
288\r
289 ; LISTST\r
290 ; List Output Status. Return true if\r
291 ; all selected list output devices\r
292 ; are ready.\r
293\r
294listst:\r
295 ld hl,(@lovec) ; get list output bit vector\r
296 jr ost$scan\r
297\r
298\r
299 ; AUXOST\r
300 ; Auxiliary Output Status. Return true if\r
301 ; all selected auxiliary output devices\r
302 ; are ready.\r
303\r
304auxost:\r
305 ld hl,(@aovec) ; get aux output bit vector\r
306 jr ost$scan\r
307\r
308\r
309 ; CONOST\r
310 ; Console Output Status. Return true if\r
311 ; all selected console output devices\r
312 ; are ready.\r
313\r
314conost:\r
315 ld hl,(@covec) ; get console output bit vector\r
316\r
317ost$scan:\r
318 ld b,0 ; start with device 0\r
319cos$next:\r
320 add hl,hl ; check next bit\r
321 push hl ; save the vector\r
322 push bc ; save the count\r
323 ld a,0FFh ; assume device ready\r
324 call c,?cost ; check status for this device\r
325 pop bc ; recover count\r
326 pop hl ; recover bit vector\r
327 or a ; see if device ready\r
328 ret z ; if any not ready, return false\r
329 inc b ; drop device number\r
330 ld a,h\r
331 or l ; see if any more selected devices\r
332 jr nz,cos$next\r
333 or 0FFh ; all selected were ready, return true\r
334 ret\r
335\r
336\r
337cist1: ; get input status with <BC> and <HL> saved\r
338 push bc\r
339 push hl\r
340 call ?cist\r
341 pop hl\r
342 pop bc\r
343 or a\r
344 ret\r
345\r
346\r
347 ; AUXIST\r
348 ; Auxiliary Input Status. Return true if\r
349 ; any selected auxiliary input device\r
350 ; has an available character.\r
351\r
352auxist:\r
353 ld hl,(@aivec) ; get aux input bit vector\r
354 jr ist$scan\r
355\r
356\r
357 ; CONST\r
358 ; Console Input Status. Return true if\r
359 ; any selected console input device\r
360 ; has an available character.\r
361\r
362const:\r
363 ld hl,(@civec) ; get console input bit vector\r
364\r
365ist$scan:\r
366 ld b,0 ; start with device 0\r
367cis$next:\r
368 xor a ; assume next device not ready\r
369 add hl,hl ; check next bit (lets z flag unaffected)\r
370 call c,cist1 ; check status for this device\r
371 ret nz ; if any ready, return true\r
372 inc b ; next device number\r
373 ld a,h\r
374 or l ; see if any more selected devices\r
375 ret z ; all selected were not ready, return false\r
376 jr cis$next\r
377\r
378\r
379 ; AUXIN\r
380 ; Auxiliary Input. Return character from first\r
381 ; ready auxiliary input device.\r
382\r
383auxin:\r
384 ld hl,(@aivec)\r
385 jr in$scan\r
386\r
387\r
388 ; CONIN\r
389 ; Console Input. Return character from first\r
390 ; ready console input device.\r
391\r
392conin:\r
393 ld hl,(@civec)\r
394\r
395 ;check if only one device assigned\r
396\r
397 push hl ; save bit vector\r
398 ld b,0\r
399insc_0:\r
400 or a ; clear carry\r
401 adc hl,hl ; shift out next bit\r
402 jr nc,insc_1 ;\r
403 jr z,ci$rdy ; single device\r
404 jr ci$check ;\r
405\r
406insc_1:\r
407 inc b ; else, next device\r
408 ld a,h\r
409 or l ; see if any more devices\r
410 jr nz,insc_0 ; no,\r
411 pop hl\r
412\r
413in$scan:\r
414 push hl ; save bit vector\r
415 ld b,0\r
416ci$next:\r
417 xor a ; assume next device not ready\r
418 add hl,hl ; shift out next bit\r
419ci$check:\r
420 call c,cist1 ; see if the device has a character\r
421 jr nz,ci$rdy ; this device has a character\r
422 inc b ; else, next device\r
423 ld a,h\r
424 or l ; see if any more devices\r
425 jr nz,ci$next ; go look at them\r
426 pop hl ; recover bit vector\r
427 jr in$scan ; loop til we find a character\r
428\r
429ci$rdy:\r
430 pop hl ; discard extra stack\r
431 jp ?ci\r
432\r
433\r
434;-------------------------------------------------------------------------------\r
435; Utility Subroutines\r
436\r
437 ; BNKSEL\r
438 ; Bank Select. Select CPU bank for further execution.\r
439\r
440bnksel:\r
441 ld (@cbnk),a ; remember current bank\r
442 jp ?bank ; and go exit through users\r
443 ; physical bank select routine\r
444\r
445 dseg ; following resides in banked memory\r
446\r
447; Disk I/O interface routines\r
448\r
449\r
450 ; SELDSK\r
451 ; Select Disk Drive. Drive code in <C>.\r
452 ; Invoke login procedure for drive\r
453 ; if this is first select. Return\r
454 ; address of disk parameter header\r
455 ; in <HL>\r
456\r
457seldsk:\r
458 ld a,c ; save drive select code\r
459 ld (@adrv),a\r
460 xor a\r
461 ld (@op),a\r
462 ld (@cnt),a\r
463 ld b,a ; create index from drive code\r
464 ld hl,@dtbl\r
465 add hl,bc ; get pointer to dispatch table\r
466 add hl,bc\r
467 ld a,(hl)\r
468 inc hl\r
469 ld h,(hl)\r
470 ld l,a ; point at disk descriptor\r
471 ld (@xdph),hl ; save descriptor pointer\r
472 or h\r
473 ret z ; if no entry in table, no disk\r
474\r
475 bit 0,e ; login bit to zero flag\r
476 ex de,hl\r
477 ld hl,-2 ; get relative drive\r
478 add hl,de\r
479 ld a,(hl)\r
480 ld (@RDRV),a\r
481 jr nz,notfirst ; examine login bit\r
482\r
483 ld hl,-6 ; call LOGIN\r
484 add hl,de\r
485 ld a,(hl)\r
486 inc hl\r
487 ld h,(hl)\r
488 ld l,a\r
489 call _b0hlcall\r
490\r
491notfirst:\r
492 ld hl,(@xdph) ; recover DPH pointer\r
493 ret\r
494\r
495\r
496 ; HOME\r
497 ; Home selected drive. Treated as SETTRK(0).\r
498\r
499home:\r
500 ld bc,0 ; same as set track zero\r
501\r
502\r
503 ; SETTRK\r
504 ; Set Track. Saves track address from <BC>\r
505 ; in @TRK for further operations.\r
506\r
507settrk:\r
508 ld (@trk),bc\r
509 ret\r
510\r
511\r
512 ; SETSEC\r
513 ; Set Sector. Saves sector number from <BC>\r
514 ; in @sect for further operations.\r
515\r
516setsec:\r
517 ld (@sect),bc\r
518 ret\r
519\r
520\r
521 ; SETDMA\r
522 ; Set Disk Memory Address. Saves DMA address\r
523 ; from <BC> in @DMA and sets @DBNK to @CBNK\r
524 ; so that further disk operations take place\r
525 ; in current bank.\r
526\r
527setdma:\r
528 ld (@dma),bc\r
529\r
530 ld a,(@cbnk) ; default DMA bank is current bank\r
531 ; fall through to set DMA bank\r
532\r
533 ; SETBNK\r
534 ; Set Disk Memory Bank. Saves bank number\r
535 ; in @DBNK for future disk data\r
536 ; transfers.\r
537\r
538setbnk:\r
539 ld (@dbnk),a\r
540 ret\r
541\r
542\r
543 ; SECTRN\r
544 ; Sector Translate. Indexes skew table in <DE>\r
545 ; with sector in <BC>. Returns physical sector\r
546 ; in <HL>. If no skew table (<DE>=0) then\r
547 ; returns physical=logical.\r
548\r
549sectrn:\r
550 ld l,c\r
551 ld h,b\r
552 ld a,d\r
553 or e\r
554 ret z\r
555 ex de,hl\r
556 add hl,bc\r
557 ld l,(hl)\r
558 ld h,0\r
559 ret\r
560\r
561\r
562 ; READ\r
563 ; Read physical record from currently selected drive.\r
564 ; Finds address of proper read routine from\r
565 ; extended disk parameter header (XDPH).\r
566\r
567read:\r
568 ld a,1\r
569 ld (@op),a\r
570 ld ix,(@xdph) ; get drive descriptor pointer\r
571 ld l,(ix-8) ; get read routine entry\r
572 ld h,(ix-7)\r
573\r
574 call _b0hlcall\r
575 ret\r
576\r
577 ; WRITE\r
578 ; Write physical sector from currently selected drive.\r
579 ; Finds address of proper write routine from\r
580 ; extended disk parameter header (XDPH).\r
581\r
582write:\r
583 ld a,2\r
584 ld (@op),a\r
585 ld ix,(@xdph) ; get drive descriptor pointer\r
586 ld l,(ix-10) ; get write routine entry\r
587 ld h,(ix- 9)\r
588\r
589 call _b0hlcall\r
590 ret\r
591\r
592\r
593\r
594 ; MULTIO\r
595 ; Set multiple sector count. Saves passed count in\r
596 ; @CNT\r
597\r
598multio:\r
599 ld (@cnt),a\r
600 ret\r
601\r
602\r
603 ; FLUSH\r
604 ; BIOS deblocking buffer flush. Not implemented.\r
605\r
606flush:\r
607 xor a\r
608 ret ; return with no error\r
609\r
610\r
611; disk communication data items\r
612; do not change order. sd driver depends on this\r
613\r
614@xdph: ds 2 ; pointer to currently selected drives dph\r
615@op ds 1 ; current disk operation 0:select, 1:read, 2 write\r
616@adrv: ds 1 ; currently selected disk drive\r
617@rdrv: ds 1 ; controller relative disk drive\r
618@trk: ds 2 ; current track number\r
619@sect: ds 2 ; current sector number\r
620@dma: ds 2 ; current DMA address\r
621@dbnk: db 0 ; bank for DMA operations\r
622@cnt: db 0 ; record count for multisector transfer\r
623\r
624\r
625 cseg ; common memory\r
626\r
627@cbnk: db 0 ; bank for processor operations\r
628\r
629 end\r