]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blob - cbios/bioskrnl.180
6ae7073117f0a230c67c5cbc402900a729a449d0
[z180-stamp-cpm3.git] / cbios / bioskrnl.180
1 title 'Root module of relocatable BIOS for CP/M 3.0'
2
3 ; version 1.0 15 Sept 82
4
5 include config.inc
6 include z180reg.inc
7
8
9 ; Copyright (C), 1982
10 ; Digital Research, Inc
11 ; P.O. Box 579
12 ; Pacific Grove, CA 93950
13
14
15 ; This is the invariant portion of the modular BIOS and is
16 ; distributed as source for informational purposes only.
17 ; All desired modifications should be performed by
18 ; adding or changing externally defined modules.
19 ; This allows producing "standard" I/O modules that
20 ; can be combined to support a particular system
21 ; configuration.
22
23 cr equ 13
24 lf equ 10
25 bell equ 7
26 ctlQ equ 'Q'-'@'
27 ctlS equ 'S'-'@'
28
29 ccp equ 0100h ; Console Command Processor gets loaded
30 ; into the TPA
31
32 cseg ; GENCPM puts CSEG stuff in common memory
33
34
35 ; variables in system data page
36
37 extrn @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors
38 extrn @mxtpa ; addr of system entry point
39 extrn @bnkbf ; 128 byte scratch buffer
40
41 ; initialization
42
43 extrn hwinit,?init ; general initialization and signon
44 extrn ?ldccp,?rlccp ; load & reload CCP for BOOT & WBOOT
45
46 ; user defined character I/O routines
47
48 extrn ?ci,?co,?cist,?cost ; each take device in <B>
49 extrn ?cinit ; (re)initialize device in <C>
50 extrn @ctbl ; physical character device table
51
52 ; disk communication data items
53
54 extrn @dtbl ; table of pointers to XDPHs
55 public @adrv,@rdrv,@trk,@sect ; parameters for disk I/O
56 public @dma,@dbnk,@cnt ; '' '' '' ''
57
58 ; memory control
59
60 public @cbnk ; current bank
61 extrn ?xmove,?move ; select move bank, and block move
62 extrn ?bank ; select CPU bank
63
64 ; clock support
65
66 extrn ?time ; signal time operation
67
68 ; general utility routines
69
70 public ?pmsg,?pdec ; print message, print number from 0 to 65535
71 public ?pderr ; print BIOS disk error message header
72 public pmsg.in ; print message inline
73 public phex4,phex2 ; print 4 digit hex (HL), or 2 digit hex (A)
74
75 include modebaud.inc ; define mode bits
76
77
78 ; External names for BIOS entry points
79
80 public ?boot,?wboot,?const,?conin,?cono,?list,?auxo,?auxi
81 public ?home,?sldsk,?sttrk,?stsec,?stdma,?read,?write
82 public ?lists,?sctrn
83 public ?conos,?auxis,?auxos,?dvtbl,?devin,?drtbl
84 public ?mltio,?flush,?mov,?tim,?bnksl,?stbnk,?xmov
85
86 public bs$stack
87
88
89 ; BIOS Jump vector.
90
91 ; All BIOS routines are invoked by calling these
92 ; entry points.
93
94 ?boot: jp boot ; initial entry on cold start
95 ?wboot: jp wboot ; reentry on program exit, warm start
96
97 ?const: jp const ; return console input status
98 ?conin: jp conin ; return console input character
99 ?cono: jp conout ; send console output character
100 ?list: jp list ; send list output character
101 ?auxo: jp auxout ; send auxiliary output character
102 ?auxi: jp auxin ; return auxiliary input character
103
104 ?home: jp home ; set disks to logical home
105 ?sldsk: jp seldsk ; select disk drive, return disk parameter info
106 ?sttrk: jp settrk ; set disk track
107 ?stsec: jp setsec ; set disk sector
108 ?stdma: jp setdma ; set disk I/O memory address
109 ?read: jp read ; read physical block(s)
110 ?write: jp write ; write physical block(s)
111
112 ?lists: jp listst ; return list device status
113 ?sctrn: jp sectrn ; translate logical to physical sector
114
115 ?conos: jp conost ; return console output status
116 ?auxis: jp auxist ; return aux input status
117 ?auxos: jp auxost ; return aux output status
118 ?dvtbl: jp devtbl ; return address of device def table
119 ?devin: jp ?cinit ; change baud rate of device
120
121 ?drtbl: jp getdrv ; return address of disk drive table
122 ?mltio: jp multio ; set multiple record count for disk I/O
123 ?flush: jp flush ; flush BIOS maintained disk caching
124
125 ?mov: jp ?move ; block move memory to memory
126 ?tim: jp ?time ; Signal Time and Date operation
127 ?bnksl: jp bnksel ; select bank for code execution and default DMA
128 ?stbnk: jp setbnk ; select different bank for disk I/O DMA operations
129 ?xmov: jp ?xmove ; set source and destination banks for one operation
130
131 jp 0 ; reserved for future expansion
132 jp 0 ; reserved for future expansion
133 jp 0 ; reserved for future expansion
134
135
136 ; BOOT
137 ; Initial entry point for system startup.
138
139 dseg ; this part can be banked
140
141 boot:
142 ld sp,bs$stack
143
144 call hwinit ; first time hardware initialisation
145
146 ld c,15 ; initialize all 16 character devices
147 c$init$loop:
148 push bc
149 call ?cinit
150 pop bc
151 dec c
152 jp p,c$init$loop
153
154 call ?init ; perform any additional system initialization
155 ; and print signon message
156
157 ld bc,16*256+0
158 ld hl,@dtbl ; init all 16 logical disk drives
159 d$init$loop:
160 push bc ; save remaining count and abs drive
161 ld e,(hl)
162 inc hl
163 ld d,(hl)
164 inc hl ; grab @drv entry
165 ld a,e
166 or d
167 jr z,d$init$next ; if null, no drive
168 push hl ; save @drv pointer
169 if 0
170 ex de,hl ; XDPH address in <HL>
171 dec hl
172 dec hl
173 ld b,(hl) ; get relative drive code
174 ld (@ADRV),bc ; save absolute and relative drive code
175 dec hl ; point to init pointer
176 ld d,(hl)
177 dec hl
178 ld e,(hl) ; get init pointer
179 ex de,hl
180 call ipchl ; call init routine
181 else
182 push de
183 pop ix
184 ld b,(ix-2)
185 ld (@ADRV),bc ; save absolute and relative drive code
186 ld l,(ix-4)
187 ld h,(ix-3) ; get init pointer
188 call ipchl ; call init routine
189 endif
190 pop hl ; recover @drv pointer
191 d$init$next:
192 pop bc ; recover counter and drive #
193 inc c
194 djnz d$init$loop ; and loop for each drive
195 jp boot$1
196
197 cseg ; following in resident memory
198
199 boot$1:
200 call set$jumps
201 call ?ldccp ; fetch CCP for first time
202 jp ccp
203
204
205 ; WBOOT
206 ; Entry for system restarts.
207
208 wboot:
209 ld sp,bs$stack
210 call set$jumps ; initialize page zero
211 call ?rlccp ; reload CCP
212 jp ccp ; then reset jmp vectors and exit to ccp
213
214
215 set$jumps:
216
217 if banked
218 ld a,1
219 call ?bnksl
220 endif
221
222 ld a,0C3h ; jp opcode
223 ld (0),a
224 ld (5),a ; set up jumps in page zero
225 ld hl,?wboot
226 ld (1),hl ; BIOS warm start entry
227 ld hl,(@MXTPA)
228 ld (6),hl ; BDOS system call entry
229 ret
230
231
232 ds 64
233 bs$stack equ $
234
235
236 ; DEVTBL
237 ; Return address of character device table
238
239 devtbl:
240 ld hl,@ctbl
241 ret
242
243
244 ; GETDRV
245 ; Return address of drive table
246
247 getdrv:
248 ld hl,@dtbl
249 ret
250
251
252
253 ; CONOUT
254 ; Console Output. Send character in <C>
255 ; to all selected devices
256
257 conout:
258
259 ld hl,(@covec) ; fetch console output bit vector
260 jr out$scan
261
262
263 ; AUXOUT
264 ; Auxiliary Output. Send character in <C>
265 ; to all selected devices
266
267 auxout:
268 ld hl,(@aovec) ; fetch aux output bit vector
269 jr out$scan
270
271
272 ; LIST
273 ; List Output. Send character in <C>
274 ; to all selected devices.
275
276 list:
277 ld hl,(@lovec) ; fetch list output bit vector
278
279 out$scan:
280 ld b,0 ; start with device 0
281 co$next:
282 add hl,hl ; shift out next bit
283 jr nc,not$out$device
284 push hl ; save the vector
285 push bc ; save the count and character
286 not$out$ready:
287 call coster
288 or a
289 jp z,not$out$ready
290 pop bc
291 push bc ; restore and resave the character and device
292 call ?co ; if device selected, print it
293 pop bc ; recover count and character
294 pop hl ; recover the rest of the vector
295 not$out$device:
296 inc b ; next device number
297 ld a,h
298 or l ; see if any devices left
299 jr nz,co$next ; and go find them...
300 ret
301
302
303 ; CONOST
304 ; Console Output Status. Return true if
305 ; all selected console output devices
306 ; are ready.
307
308 conost:
309 ld hl,(@covec) ; get console output bit vector
310 jr ost$scan
311
312
313 ; AUXOST
314 ; Auxiliary Output Status. Return true if
315 ; all selected auxiliary output devices
316 ; are ready.
317
318 auxost:
319 ld hl,(@aovec) ; get aux output bit vector
320 jr ost$scan
321
322
323 ; LISTST
324 ; List Output Status. Return true if
325 ; all selected list output devices
326 ; are ready.
327
328 listst:
329 ld hl,(@lovec) ; get list output bit vector
330
331 ost$scan:
332 ld b,0 ; start with device 0
333 cos$next:
334 add hl,hl ; check next bit
335 push hl ; save the vector
336 push bc ; save the count
337 ld a,0FFh ; assume device ready
338 call c,coster ; check status for this device
339 pop bc ; recover count
340 pop hl ; recover bit vector
341 or a ; see if device ready
342 ret z ; if any not ready, return false
343 inc b ; drop device number
344 ld a,h
345 or l ; see if any more selected devices
346 jr nz,cos$next
347 or 0FFh ; all selected were ready, return true
348 ret
349
350 coster: ; check for output device ready, including optional
351 ; xon/xoff support
352 ld l,b
353 ld h,0 ; make device code 16 bits
354 push hl ; save it in stack
355 add hl,hl
356 add hl,hl
357 add hl,hl ; create offset into device characteristics tbl
358 ld de,@ctbl+6
359 add hl,de ; make address of mode byte
360 ld a,(hl)
361 and mb$xon$xoff
362 pop hl ; recover console number in <HL>
363 jp z,?cost ; not a xon device, go get output status direct
364 ld de,xofflist
365 add hl,de ; make pointer to proper xon/xoff flag
366 call cist1 ; see if this keyboard has character
367 ld a,(hl)
368 call nz,ci1 ; get flag or read key if any
369 cp ctlq
370 jr nz,not$q ; if its a ctl-Q,
371 ld a,0FFh ; set the flag ready
372 not$q:
373 cp ctls
374 jr nz,not$s ; if its a ctl-S,
375 ld a,00h ; clear the flag
376 not$s:
377 ld (hl),a ; save the flag
378 call cost1 ; get the actual output status,
379 and (hl) ; and mask with ctl-Q/ctl-S flag
380 ret ; return this as the status
381
382 cist1: ; get input status with <BC> and <HL> saved
383 push bc
384 push hl
385 call ?cist
386 pop hl
387 pop bc
388 or a
389 ret
390
391 cost1: ; get output status, saving <BC> & <HL>
392 push bc
393 push hl
394 call ?cost
395 pop hl
396 pop bc
397 or a
398 ret
399
400 ci1: ; get input, saving <BC> & <HL>
401 push bc
402 push hl
403 call ?ci
404 pop hl
405 pop bc
406 ret
407
408
409 ; CONST
410 ; Console Input Status. Return true if
411 ; any selected console input device
412 ; has an available character.
413
414 const:
415 ld hl,(@civec) ; get console input bit vector
416 jr ist$scan
417
418
419 ; AUXIST
420 ; Auxiliary Input Status. Return true if
421 ; any selected auxiliary input device
422 ; has an available character.
423
424 auxist:
425 ld hl,(@aivec) ; get aux input bit vector
426
427 ist$scan:
428 ld b,0 ; start with device 0
429 cis$next:
430 add hl,hl ; check next bit
431 ld a,0 ; assume device not ready
432 call c,cist1 ; check status for this device
433 or a
434 ret nz ; if any ready, return true
435 inc b ; next device number
436 ld a,h
437 or l ; see if any more selected devices
438 jr nz,cis$next
439 xor a ; all selected were not ready, return false
440 ret
441
442
443 ; CONIN
444 ; Console Input. Return character from first
445 ; ready console input device.
446
447 conin:
448 ld hl,(@civec)
449 jr in$scan
450
451
452 ; AUXIN
453 ; Auxiliary Input. Return character from first
454 ; ready auxiliary input device.
455
456 auxin:
457 ld hl,(@aivec)
458
459 in$scan:
460 push hl ; save bit vector
461 ld b,0
462 ci$next:
463 add hl,hl ; shift out next bit
464 ld a,0 ; insure zero a (nonexistant device not ready).
465 call c,cist1 ; see if the device has a character
466 or a
467 jr nz,ci$rdy ; this device has a character
468 inc b ; else, next device
469 ld a,h
470 or l ; see if any more devices
471 jr nz,ci$next ; go look at them
472 pop hl ; recover bit vector
473 jr in$scan ; loop til we find a character
474
475 ci$rdy:
476 pop hl ; discard extra stack
477 jp ?ci
478
479
480 ;-------------------------------------------------------------------------------
481 ; Utility Subroutines
482
483
484 ipchl: ; vectored CALL point
485 jp (hl)
486
487
488 ;-------------------------------------------------------------------------------
489 ; print message @<HL> up to a null
490 ; saves <BC> & <DE>
491
492 ?pmsg:
493 push bc
494 push de
495 pmsg$loop:
496 ld a,(hl)
497 or a
498 jr z,pmsg$exit
499 ld c,a
500 push hl
501 call ?cono
502 pop hl
503 inc hl
504 jr pmsg$loop
505 pmsg$exit:
506 pop de
507 pop bc
508 ret
509
510 ;-------------------------------------------------------------------------------
511 ; print message inline up to a null
512 ; saves all registers
513
514 pmsg.in:
515 ex (sp),hl
516 push af
517 call ?pmsg
518 pop af
519 ex (sp),hl
520 ret
521
522 ;-------------------------------------------------------------------------------
523 ; print hl as a 4 digit hexadecimal number
524 ; saves all registers
525
526 phex4:
527 ld a,h
528 call phex2
529 ld a,l
530 ; fall thru
531
532 ;-------------------------------------------------------------------------------
533 ; print a as a 2 digit hexadecimal number
534 ; saves all registers
535
536 phex2:
537 push af
538 rra
539 rra
540 rra
541 rra
542 call print.digit
543 pop af
544
545 print.digit:
546 push hl
547 push de
548 push bc
549 push af
550 and 00fh
551 cp 10
552 jr c,prd_1
553 add a,007h
554 prd_1:
555 add a,'0'
556
557 ld c,a
558 call ?cono
559 pop af
560 pop bc
561 pop de
562 pop hl
563 ret
564
565 ;-------------------------------------------------------------------------------
566
567 ?pdec: ; print binary number 0-65535 from <HL>
568 ld bc,table10
569 ld de,-10000
570 next:
571 ld a,'0'-1
572 pdecl:
573 push hl
574 inc a
575 add hl,de
576 jp nc,stoploop
577 inc sp
578 inc sp
579 jp pdecl
580 stoploop:
581 push de
582 push bc
583 ld c,a
584 call ?cono
585 pop bc
586 pop de
587 nextdigit:
588 pop hl
589 ld a,(bc)
590 ld e,a
591 inc bc
592 ld a,(bc)
593 ld d,a
594 inc bc
595 ld a,e
596 or d
597 jp nz,next
598 ret
599
600 table10:
601 dw -1000,-100,-10,-1,0
602
603 ?pderr:
604 ld hl,drive$msg
605 call ?pmsg ; error header
606 ld a,(@adrv)
607 add a,'A'
608 ld c,a
609 call ?cono ; drive code
610 ld hl,track$msg
611 call ?pmsg ; track header
612 ld hl,(@trk)
613 call ?pdec ; track number
614 ld hl,sector$msg
615 call ?pmsg ; sector header
616 ld hl,(@sect)
617 call ?pdec ; sector number
618 ret
619
620
621 ; BNKSEL
622 ; Bank Select. Select CPU bank for further execution.
623
624 bnksel:
625 ld (@cbnk),a ; remember current bank
626 jp ?bank ; and go exit through users
627 ; physical bank select routine
628
629
630 xofflist:
631 db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero
632 db -1,-1,-1,-1,-1,-1,-1,-1
633
634
635
636 dseg ; following resides in banked memory
637
638
639
640 ; Disk I/O interface routines
641
642
643 ; SELDSK
644 ; Select Disk Drive. Drive code in <C>.
645 ; Invoke login procedure for drive
646 ; if this is first select. Return
647 ; address of disk parameter header
648 ; in <HL>
649
650 seldsk:
651 ld a,c ; save drive select code
652 ld (@adrv),a
653 ld b,0 ; create index from drive code
654 ld hl,@dtbl
655 add hl,bc ; get pointer to dispatch table
656 add hl,bc
657 ld a,(hl)
658 inc hl
659 ld h,(hl)
660 ld l,a ; point at disk descriptor
661 ld (@xdph),hl ; save descriptor pointer
662 or h
663 ret z ; if no entry in table, no disk
664
665 ld a,e ; examine login bit
666 and 1
667 ret nz
668
669 push ix
670 ld ix,(@xdph)
671 ld a,(ix-2)
672 ld (@RDRV),a ; get relative drive
673 ld l,(ix-6) ; get address of LOGIN routine
674 ld h,(ix-5)
675 ex (sp),ix
676 pop de
677 call ipchl ; call LOGIN
678 ld hl,(@xdph) ; recover DPH pointer
679 ret
680
681
682 ; HOME
683 ; Home selected drive. Treated as SETTRK(0).
684
685 home:
686 ld bc,0 ; same as set track zero
687
688
689 ; SETTRK
690 ; Set Track. Saves track address from <BC>
691 ; in @TRK for further operations.
692
693 settrk:
694 ld (@trk),bc
695 ret
696
697
698 ; SETSEC
699 ; Set Sector. Saves sector number from <BC>
700 ; in @sect for further operations.
701
702 setsec:
703 ld (@sect),bc
704 ret
705
706
707 ; SETDMA
708 ; Set Disk Memory Address. Saves DMA address
709 ; from <BC> in @DMA and sets @DBNK to @CBNK
710 ; so that further disk operations take place
711 ; in current bank.
712
713 setdma:
714 ld (@dma),bc
715
716 ld a,(@cbnk) ; default DMA bank is current bank
717 ; fall through to set DMA bank
718
719 ; SETBNK
720 ; Set Disk Memory Bank. Saves bank number
721 ; in @DBNK for future disk data
722 ; transfers.
723
724 setbnk:
725 ld (@dbnk),a
726 ret
727
728
729 ; SECTRN
730 ; Sector Translate. Indexes skew table in <DE>
731 ; with sector in <BC>. Returns physical sector
732 ; in <HL>. If no skew table (<DE>=0) then
733 ; returns physical=logical.
734
735 sectrn:
736 ld l,c
737 ld h,b
738 ld a,d
739 or e
740 ret z
741 ex de,hl
742 add hl,bc
743 ld l,(hl)
744 ld h,0
745 ret
746
747
748 ; READ
749 ; Read physical record from currently selected drive.
750 ; Finds address of proper read routine from
751 ; extended disk parameter header (XDPH).
752
753 read:
754 ld ix,(@xdph) ; get drive descriptor pointer
755 ld l,(ix-8) ; get read routine entry
756 ld h,(ix-7)
757 jp (hl)
758
759
760 ; WRITE
761 ; Write physical sector from currently selected drive.
762 ; Finds address of proper write routine from
763 ; extended disk parameter header (XDPH).
764
765 write:
766 ld ix,(@xdph) ; get drive descriptor pointer
767 ld l,(ix-10) ; get write routine entry
768 ld h,(ix- 9)
769 jp (hl)
770
771
772
773 ; MULTIO
774 ; Set multiple sector count. Saves passed count in
775 ; @CNT
776
777 multio:
778 ld (@cnt),a
779 ret
780
781
782 ; FLUSH
783 ; BIOS deblocking buffer flush. Not implemented.
784
785 flush:
786 xor a
787 ret ; return with no error
788
789
790
791 ; error message components
792 drive$msg: db cr,lf,bell,'BIOS Error on ',0
793 track$msg: db ': T-',0
794 sector$msg: db ', S-',0
795
796
797 ; disk communication data items
798 ; do not change order. sd driver depends on this
799
800 @xdph: ds 2 ; pointer to currently selected drives dph
801 @adrv: ds 1 ; currently selected disk drive
802 @rdrv: ds 1 ; controller relative disk drive
803 @cnt: db 0 ; record count for multisector transfer
804 @trk: ds 2 ; current track number
805 @sect: ds 2 ; current sector number
806 @dma: ds 2 ; current DMA address
807 @dbnk: db 0 ; bank for DMA operations
808
809
810 cseg ; common memory
811
812 @cbnk: db 0 ; bank for processor operations
813
814
815 end