1 title 'Root module of relocatable BIOS for CP/M 3.0'
3 ; version 1.0 15 Sept 82
10 ; Digital Research, Inc
12 ; Pacific Grove, CA 93950
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
29 ccp equ 0100h ; Console Command Processor gets loaded
32 cseg ; GENCPM puts CSEG stuff in common memory
35 ; variables in system data page
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
43 extrn hwinit,?init ; general initialization and signon
44 extrn ?ldccp,?rlccp ; load & reload CCP for BOOT & WBOOT
46 ; user defined character I/O routines
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
52 ; disk communication data items
54 extrn @dtbl ; table of pointers to XDPHs
55 public @adrv,@rdrv,@trk,@sect ; parameters for disk I/O
56 public @dma,@dbnk,@cnt ; '' '' '' ''
60 public @cbnk ; current bank
61 extrn ?xmove,?move ; select move bank, and block move
62 extrn ?bank ; select CPU bank
66 extrn ?time ; signal time operation
68 ; general utility routines
70 public ?pmsg ; print message
71 public pr.dec,pr.decl ; print 16 or 32 bit decimal number
72 public ?pderr ; print BIOS disk error message header
73 public pr.inln,pr.crlf ; print message inline
74 public phex4,phex2 ; print 4 digit hex (HL), or 2 digit hex (A)
76 extrn div32_16 ; divide 32 bit by 16 bit number
78 include modebaud.inc ; define mode bits
81 ; External names for BIOS entry points
83 public ?boot,?wboot,?const,?conin,?cono,?list,?auxo,?auxi
84 public ?home,?sldsk,?sttrk,?stsec,?stdma,?read,?write
86 public ?conos,?auxis,?auxos,?dvtbl,?devin,?drtbl
87 public ?mltio,?flush,?mov,?tim,?bnksl,?stbnk,?xmov
94 ; All BIOS routines are invoked by calling these
97 ?boot: jp boot ; initial entry on cold start
98 ?wboot: jp wboot ; reentry on program exit, warm start
100 ?const: jp const ; return console input status
101 ?conin: jp conin ; return console input character
102 ?cono: jp conout ; send console output character
103 ?list: jp list ; send list output character
104 ?auxo: jp auxout ; send auxiliary output character
105 ?auxi: jp auxin ; return auxiliary input character
107 ?home: jp home ; set disks to logical home
108 ?sldsk: jp seldsk ; select disk drive, return disk parameter info
109 ?sttrk: jp settrk ; set disk track
110 ?stsec: jp setsec ; set disk sector
111 ?stdma: jp setdma ; set disk I/O memory address
112 ?read: jp read ; read physical block(s)
113 ?write: jp write ; write physical block(s)
115 ?lists: jp listst ; return list device status
116 ?sctrn: jp sectrn ; translate logical to physical sector
118 ?conos: jp conost ; return console output status
119 ?auxis: jp auxist ; return aux input status
120 ?auxos: jp auxost ; return aux output status
121 ?dvtbl: jp devtbl ; return address of device def table
122 ?devin: jp ?cinit ; change baud rate of device
124 ?drtbl: jp getdrv ; return address of disk drive table
125 ?mltio: jp multio ; set multiple record count for disk I/O
126 ?flush: jp flush ; flush BIOS maintained disk caching
128 ?mov: jp ?move ; block move memory to memory
129 ?tim: jp ?time ; Signal Time and Date operation
130 ?bnksl: jp bnksel ; select bank for code execution and default DMA
131 ?stbnk: jp setbnk ; select different bank for disk I/O DMA operations
132 ?xmov: jp ?xmove ; set source and destination banks for one operation
134 jp 0 ; reserved for future expansion
135 jp 0 ; reserved for future expansion
136 jp 0 ; reserved for future expansion
140 ; Initial entry point for system startup.
142 dseg ; this part can be banked
147 call hwinit ; first time hardware initialisation
149 ld bc,16*256 + 0 ; initialize all 16 character devices
157 call ?init ; perform any additional system initialization
158 ; and print signon message
161 ld hl,@dtbl ; init all 16 logical disk drives
163 push bc ; save remaining count and abs drive
167 inc hl ; grab @drv entry
170 jr z,d$init$next ; if null, no drive
171 push hl ; save @drv pointer
173 ex de,hl ; XDPH address in <HL>
176 ld b,(hl) ; get relative drive code
177 ld (@ADRV),bc ; save absolute and relative drive code
178 dec hl ; point to init pointer
181 ld e,(hl) ; get init pointer
183 call ipchl ; call init routine
188 ld (@ADRV),bc ; save absolute and relative drive code
190 ld h,(ix-3) ; get init pointer
191 call ipchl ; call init routine
193 pop hl ; recover @drv pointer
195 pop bc ; recover counter and drive #
197 djnz d$init$loop ; and loop for each drive
200 cseg ; following in resident memory
204 call ?ldccp ; fetch CCP for first time
209 ; Entry for system restarts.
213 call set$jumps ; initialize page zero
214 call ?rlccp ; reload CCP
215 jp ccp ; then reset jmp vectors and exit to ccp
225 ld a,0C3h ; jp opcode
227 ld (5),a ; set up jumps in page zero
229 ld (1),hl ; BIOS warm start entry
231 ld (6),hl ; BDOS system call entry
240 ; Return address of character device table
248 ; Return address of drive table
257 ; Console Output. Send character in <C>
258 ; to all selected devices
262 ld hl,(@covec) ; fetch console output bit vector
267 ; Auxiliary Output. Send character in <C>
268 ; to all selected devices
271 ld hl,(@aovec) ; fetch aux output bit vector
276 ; List Output. Send character in <C>
277 ; to all selected devices.
280 ld hl,(@lovec) ; fetch list output bit vector
283 ld b,0 ; start with device 0
285 add hl,hl ; shift out next bit
287 push hl ; save the vector
288 push bc ; save the count and character
294 push bc ; restore and resave the character and device
295 call ?co ; if device selected, print it
296 pop bc ; recover count and character
297 pop hl ; recover the rest of the vector
299 inc b ; next device number
301 or l ; see if any devices left
302 jr nz,co$next ; and go find them...
307 ; Console Output Status. Return true if
308 ; all selected console output devices
312 ld hl,(@covec) ; get console output bit vector
317 ; Auxiliary Output Status. Return true if
318 ; all selected auxiliary output devices
322 ld hl,(@aovec) ; get aux output bit vector
327 ; List Output Status. Return true if
328 ; all selected list output devices
332 ld hl,(@lovec) ; get list output bit vector
335 ld b,0 ; start with device 0
337 add hl,hl ; check next bit
338 push hl ; save the vector
339 push bc ; save the count
340 ld a,0FFh ; assume device ready
341 call c,coster ; check status for this device
342 pop bc ; recover count
343 pop hl ; recover bit vector
344 or a ; see if device ready
345 ret z ; if any not ready, return false
346 inc b ; drop device number
348 or l ; see if any more selected devices
350 or 0FFh ; all selected were ready, return true
353 ; check for output device ready, including optional
357 ld h,0 ; make device code 16 bits
358 push hl ; save it in stack
361 add hl,hl ; create offset into device characteristics tbl
363 add hl,de ; make address of mode byte
366 pop hl ; recover console number in <HL>
367 jp z,?cost ; not a xon device, go get output status direct
369 add hl,de ; make pointer to proper xon/xoff flag
370 call cist1 ; see if this keyboard has character
372 call nz,ci1 ; get flag or read key if any
374 jr nz,not$q ; if its a ctl-Q,
375 ld a,0FFh ; set the flag ready
378 jr nz,not$s ; if its a ctl-S,
379 ld a,00h ; clear the flag
381 ld (hl),a ; save the flag
382 call cost1 ; get the actual output status,
383 and (hl) ; and mask with ctl-Q/ctl-S flag
384 ret ; return this as the status
386 cist1: ; get input status with <BC> and <HL> saved
395 cost1: ; get output status, saving <BC> & <HL>
404 ci1: ; get input, saving <BC> & <HL>
414 ; Console Input Status. Return true if
415 ; any selected console input device
416 ; has an available character.
419 ld hl,(@civec) ; get console input bit vector
424 ; Auxiliary Input Status. Return true if
425 ; any selected auxiliary input device
426 ; has an available character.
429 ld hl,(@aivec) ; get aux input bit vector
432 ld b,0 ; start with device 0
434 add hl,hl ; check next bit
435 ld a,0 ; assume device not ready
436 call c,cist1 ; check status for this device
438 ret nz ; if any ready, return true
439 inc b ; next device number
441 or l ; see if any more selected devices
443 xor a ; all selected were not ready, return false
448 ; Console Input. Return character from first
449 ; ready console input device.
457 ; Auxiliary Input. Return character from first
458 ; ready auxiliary input device.
464 push hl ; save bit vector
467 add hl,hl ; shift out next bit
468 ld a,0 ; insure zero a (nonexistant device not ready).
469 call c,cist1 ; see if the device has a character
471 jr nz,ci$rdy ; this device has a character
472 inc b ; else, next device
474 or l ; see if any more devices
475 jr nz,ci$next ; go look at them
476 pop hl ; recover bit vector
477 jr in$scan ; loop til we find a character
480 pop hl ; discard extra stack
484 ;-------------------------------------------------------------------------------
485 ; Utility Subroutines
488 ipchl: ; vectored CALL point
492 ;-------------------------------------------------------------------------------
493 ; print message @<HL> up to a null
514 ;-------------------------------------------------------------------------------
515 ; print message inline up to a null
516 ; saves all registers
526 ;-------------------------------------------------------------------------------
528 ; saves all registers
535 ;-------------------------------------------------------------------------------
536 ; print hl as a 4 digit hexadecimal number
537 ; saves all registers
545 ;-------------------------------------------------------------------------------
546 ; print a as a 2 digit hexadecimal number
547 ; saves all registers
579 ;-------------------------------------------------------------------------------
580 ; print decimal 16 bit number from HL
582 ; HL: unsigned binary number to print
583 ; C: minimum print field width
584 ; number is prined right-aligned
585 ; B: pad character, typically ' ' or '0'
594 ;-------------------------------------------------------------------------------
595 ; print decimal 32 bit number from DEHL
597 ; DEHL: unsigned binary number to print
598 ; C: minimum print field width
599 ; number is prined right-aligned
600 ; B: pad character, typically ' ' or '0'
603 push bc ;save width and fillchar
606 ex (sp),hl ;save hl', get width and fill
610 ld d,a ;clear counter
612 push af ; string terminator
618 call div32_16 ; get a digit
620 add a,'0' ; make it printable
632 prd_filloop: ;h=filler, l=field width
642 add hl,sp ;ptr to beginning of number string (hl==0 here)
647 inc sp ;remove string terminator
655 ;-------------------------------------------------------------------------------
659 call ?pmsg ; error header
663 call ?cono ; drive code
665 call ?pmsg ; track header
668 call pr.dec ; track number
670 call ?pmsg ; sector header
672 call pr.dec ; sector number
677 ; Bank Select. Select CPU bank for further execution.
680 ld (@cbnk),a ; remember current bank
681 jp ?bank ; and go exit through users
682 ; physical bank select routine
686 db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero
687 db -1,-1,-1,-1,-1,-1,-1,-1
691 dseg ; following resides in banked memory
695 ; Disk I/O interface routines
699 ; Select Disk Drive. Drive code in <C>.
700 ; Invoke login procedure for drive
701 ; if this is first select. Return
702 ; address of disk parameter header
706 ld a,c ; save drive select code
708 ld b,0 ; create index from drive code
710 add hl,bc ; get pointer to dispatch table
715 ld l,a ; point at disk descriptor
716 ld (@xdph),hl ; save descriptor pointer
718 ret z ; if no entry in table, no disk
720 ld a,e ; examine login bit
727 ld (@RDRV),a ; get relative drive
728 ld l,(ix-6) ; get address of LOGIN routine
732 call ipchl ; call LOGIN
733 ld hl,(@xdph) ; recover DPH pointer
738 ; Home selected drive. Treated as SETTRK(0).
741 ld bc,0 ; same as set track zero
745 ; Set Track. Saves track address from <BC>
746 ; in @TRK for further operations.
754 ; Set Sector. Saves sector number from <BC>
755 ; in @sect for further operations.
763 ; Set Disk Memory Address. Saves DMA address
764 ; from <BC> in @DMA and sets @DBNK to @CBNK
765 ; so that further disk operations take place
771 ld a,(@cbnk) ; default DMA bank is current bank
772 ; fall through to set DMA bank
775 ; Set Disk Memory Bank. Saves bank number
776 ; in @DBNK for future disk data
785 ; Sector Translate. Indexes skew table in <DE>
786 ; with sector in <BC>. Returns physical sector
787 ; in <HL>. If no skew table (<DE>=0) then
788 ; returns physical=logical.
804 ; Read physical record from currently selected drive.
805 ; Finds address of proper read routine from
806 ; extended disk parameter header (XDPH).
809 ld ix,(@xdph) ; get drive descriptor pointer
810 ld l,(ix-8) ; get read routine entry
816 ; Write physical sector from currently selected drive.
817 ; Finds address of proper write routine from
818 ; extended disk parameter header (XDPH).
821 ld ix,(@xdph) ; get drive descriptor pointer
822 ld l,(ix-10) ; get write routine entry
829 ; Set multiple sector count. Saves passed count in
838 ; BIOS deblocking buffer flush. Not implemented.
842 ret ; return with no error
846 ; error message components
847 drive$msg: db cr,lf,bell,'BIOS Error on ',0
848 track$msg: db ': T-',0
849 sector$msg: db ', S-',0
852 ; disk communication data items
853 ; do not change order. sd driver depends on this
855 @xdph: ds 2 ; pointer to currently selected drives dph
856 @adrv: ds 1 ; currently selected disk drive
857 @rdrv: ds 1 ; controller relative disk drive
858 @trk: ds 2 ; current track number
859 @sect: ds 2 ; current sector number
860 @dma: ds 2 ; current DMA address
861 @dbnk: db 0 ; bank for DMA operations
862 @cnt: db 0 ; record count for multisector transfer
867 @cbnk: db 0 ; bank for processor operations