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