]> wirehaze git hosting - MS-DOS.git/blob - v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0-ozzie / bin / DISK2 / BIOS / IBMMTCON.ASM
1 TITLE MTCON - Console device driver for MT-MSDOS
2 page ,132
3
4
5 ;; TODO -
6 ;; split CON and KBD
7 ;; interruptible waits and unwinding
8 ;; per screen keyboard buffers
9
10 ;------------------------------------------------------------------------
11 ; Revision History
12 ;
13 ; V1.00 04/10/84 M.A.Ulloa
14 ; First Implementation: Only one segment used and only
15 ; one screen in the color card (alpha mode).
16 ;
17 ; V1.01 04/15/84 M.A.Ulloa
18 ; Re-enabled the blocking of writing from processes not
19 ; with the current screen.
20 ;
21 ; V1.02 04/16/84 M.A.Ulloa
22 ; Increased to 8 the num of screens. Added the screen
23 ; blanking when reading and writing the screen data
24 ; (see BLANK switch). Added screen # for writes.
25 ;
26 ; V1.03 04/17/84 M.A.Ulloa
27 ; Corrected problem with flush.
28 ;
29 ; V1.05 04/30/84 A.R.Whitney
30 ; Added conditional compilation to allow linking with
31 ; resident BIOS.
32 ;
33 ; V1.06 05/08/84 A.R.Whitney
34 ; Added ANSI escape sequences. Conditional on ANSI.
35 ;
36 ; V1.07 05/15/84 A.R.Whitney
37 ; Fixed compatibility problems with Eagle PC Turbo.
38 ; Fixed BLANK conditional code to allow saving graphics
39 ; mode screens.
40 ; Added enable/disable 25th line to Ansi.
41 ;
42 ; V1.08 05/22/84 A.R.Whitney
43 ; Fixed problem with scrolling in screen modes other
44 ; than 80x25. Bug due to 25th line stuff.
45 ;
46 ;------------------------------------------------------------------------
47
48 ;DEBUGFLG = 1
49
50 .xlist
51 include DEFDBUG.INC
52 .list
53
54 FALSE EQU 0
55 TRUE EQU NOT FALSE
56
57 CVERS equ 01 ; update version number!!
58 CREV equ 08
59
60 BLANK equ TRUE ; blank screen during data r/w
61 INBIOS equ TRUE ; link with BIOS
62 ANSI equ TRUE ; include ANSI escape sequences
63 LINE25 equ TRUE ; special 25th line like VT52
64 EAGLE equ TRUE ; Eagle PC ROM botches CRT_LEN
65
66
67 subttl Screen Information Block Definition
68 page
69
70 ;------------------------------------------------------------------------
71 ; Screen Information Block (SIB) Definition
72 ;
73 ; This structure contains all information necessary to
74 ; describe the state of the screen, plus pointers to buffers
75 ; which contain the actual screen content.
76 ;
77
78 ;------------------------------------------------------------------------
79 MaxSEG equ 2 ; NOTE: assumption is made in the
80 ; code that all SIB's have same
81 ; number os SEGs
82 SEGst struc
83 SizeNeeded dw 0 ; needed size for seg, (0 = unused)
84 MemFlag dw ? ; maintened by system (0 = in mem)
85 MPointer dd ? ; vaild iff MemFlag == 0
86 SEGst ends
87
88 ;------------------------------------------------------------------------
89 MaxSIB equ 8 ; maximum number of Screens
90
91
92 IF ANSI
93 TermSize EQU 20 ; max. size of terminal emulation state
94 ENDIF
95
96 SIBst struc
97 ctlS db 0 ; if the screen is NOT frozen = 0
98 ; NOTE: this field should be the
99 ; FIRST of each SIB !! (see ConWrit)
100 OffsetVal dw 7 ; start of Seg Descriptors
101 SegCnt dw MaxSeg ; max number of Segments
102 SIBlen dw (SIZE SIBst) ; length of the SIB
103 ;--- Segments
104 db ((SIZE SEGst) * MaxSeg) dup (?)
105 ;--- PC video state info
106 xCRT_MODE DB ?
107 xCRT_COLS DW ?
108 xCRT_LEN DW ?
109 xCRT_START DW ?
110 xCURSOR_POSN DW 8 DUP(?)
111 xCURSOR_MODE DW ?
112 xACTIVE_PAGE DB ?
113 xADDR_6845 DW ?
114 xCRT_MODE_SET DB ?
115 xCRT_PALETTE DB ?
116 xTERM_STATE DB TermSize DUP(?)
117 SIBst ends
118
119
120 subttl Request packet definitions
121 page
122
123 ;------------------------------------------------------------------------
124 ; Request packet offset definitions
125 ;
126
127 CMDLEN = 0 ;LENGTH OF THIS COMMAND
128 UNIT = 1 ;SUB UNIT SPECIFIER
129 CMD = 2 ;COMMAND CODE
130 STATUS = 3 ;STATUS
131 MEDIA = 13 ;MEDIA DESCRIPTOR
132 TRANS = 14 ;TRANSFER ADDRESS
133 COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS
134 START = 20 ;FIRST BLOCK TO TRANSFER
135
136
137 subttl IBM-PC ROM Data area Locations
138 page
139
140 ;------------------------------------------------------------------------
141 ; IBM-PC ROM Data area Locations
142 ;
143
144 RomData SEGMENT AT 40H
145 ORG 1AH
146 BufferHead DW ?
147 BufferTail DW ?
148 KeyBuffer DW 16 DUP (?)
149 KeyBufLen equ ($-KeyBuffer) ; length of KeyBuffer
150
151 ORG 49H
152 CRT_MODE DB ?
153 CRT_COLS DW ?
154 CRT_LEN DW ?
155 CRT_START DW ?
156 CURSOR_POSN DW 8 DUP(?)
157 CURSOR_MODE DW ?
158 ACTIVE_PAGE DB ?
159 ADDR_6845 DW ?
160 CRT_MODE_SET DB ?
161 CRT_PALETTE DB ?
162
163 CrtLen EQU ($-CRT_MODE) ; length of screen state area
164 RomData ENDS
165
166 MonoSc SEGMENT AT 0B000H
167 ;--- 4k of screen memory
168 MonoSc ENDS
169
170 ColorSc SEGMENT AT 0B800H
171 ;--- 16k of screen memory
172 ColorSc ENDS
173
174 BRKADR equ 006CH ; Break vector address
175
176
177 subttl Device Header
178 page
179
180
181 BiosSeg group Code,BiosInit
182 Code Segment byte public 'CODE'
183
184 ;------------------------------------------------------------------------
185 ; Device Header
186 ;
187
188 assume cs:Code,ds:NOTHING,es:NOTHING,ss:NOTHING
189
190 PUBLIC CONDEV
191 IF INBIOS
192 extrn AUXDEV:FAR
193 CONDEV dd AUXDEV
194 ELSE
195 CONDEV dw 0FFFFh,0FFFFh
196 ENDIF ;INBIOS
197 ;*** should ioctl bit be set for gen ioctl too?
198 dw 1100000000010011b ; console in and out
199 dw Strategy
200 dw Entry
201 db "CON "
202
203
204 ;------------------------------------------------------------------------
205 ; Command dispatch table
206 ;
207
208 ComTbl:
209 ;--- 2.0
210 dw OFFSET BiosSeg:$ConInit ; Initialization function
211 dw StatusComplete ; Media Check
212 dw StatusComplete ; Build BPB
213 dw CmdErr ; IOCTL Input
214 dw $ConRead ; Input (Read)
215 dw $ConRdnd ; Non-Destructive read, no wait
216 dw StatusComplete ; Input Status
217 dw $ConFlsh ; Input Flush
218 dw $ConWrit ; Output (Write)
219 dw $ConWrit ; Output with verify
220 dw StatusComplete ; Output Status
221 dw StatusComplete ; Output Flush
222 dw StatusComplete ; IOCTL Output
223 ;--- 3.0
224 dw StatusComplete ; Device Open
225 dw StatusComplete ; Device Close
226 dw StatusComplete ; Removable Media
227 ;--- 4.0
228 dw $GenIOCTL ; Generic IOCTL
229 dw $ConStop ; Pause Device
230 dw $ConStart ; Continue Device
231
232 ComTblEnd:
233
234 CTSIZE equ (ComTblEnd - ComTbl)/2 ; number of table entries
235
236
237 subttl Device Data Area
238 page
239
240 ;------------------------------------------------------------------------
241 ; Device Data Area
242 ;
243
244 SaveFlg db 0 ; Screen being saved flag, (true = 1)
245 IF INBIOS
246 EXTRN DosFunction:DWORD
247 ELSE
248 DosFunction dd ? ; pointer to dos "helper" functions
249 ENDIF ;INBIOS
250 AltAH db 0 ; Side buffer for input
251 CurrSc dw 0 ; Current screen number
252 CurrSIB dw SIB ; offset to the current SIB
253 SIB SIBst MaxSIB dup (<>) ; allocate room for SIB's
254
255 IF EAGLE
256 ScreenLen db 08h ; table of (high byte of) regen. buffer
257 db 08h ; len. Indexed by screen mode.
258 db 10h ; 80x25 text modes
259 db 10h
260 db 40h ; graphics modes
261 db 40h
262 db 40h
263 db 10h ; monochrome
264 ENDIF
265
266
267 IFDEF DEBUGFLG
268 IF INBIOS
269 EXTRN BUGBITS:BYTE,DPRINTF:NEAR
270 ELSE
271 BUGBITS db 0ffh,0ffh
272 ENDIF
273 ENDIF
274
275 subttl Device Entry Points
276 page
277
278 ;------------------------------------------------------------------------
279 ; 2.0 Interrupt Routine (Not Used)
280 ;
281
282 EntryP proc far
283 Entry: ret
284 EntryP endp
285
286
287 ;------------------------------------------------------------------------
288 ; 2.0 Strategy Routine, main entry point
289 ;
290 ; entry
291 ; ES:BX points to Request packet
292 ;
293
294 StratP proc far
295
296 Strategy:
297 IF INBIOS
298 extrn Interrupt:NEAR
299
300 push si
301 mov si,OFFSET CS:ComTbl
302 jmp Interrupt
303 ELSE
304 push ax ; save all
305 push cx
306 push dx
307 push si
308 push di
309 push bp
310 push ds
311
312 push es ; DS = ES
313 pop ds
314
315 push es
316 push bx
317 mov al, byte ptr ds:[bx].CMD
318 cmp al,CTSIZE ; Command within range?
319 jae CmdErr ; no must be an error
320 mov cx, word ptr ds:[bx].COUNT
321 les di, dword ptr ds:[bx].TRANS
322 xor ah,ah
323 mov si, offset ComTbl
324 add si,ax
325 add si,ax
326
327 jmp word ptr cs:[si] ; dispatch
328 ENDIF ;INBIOS
329
330 StratP endp
331
332
333 subttl Exit Routines
334 page
335
336 ;------------------------------------------------------------------------
337 ; Exit Routines, Common to all device functions
338 ;
339
340 IF INBIOS
341 extrn StatusComplete:NEAR,StatusError:NEAR,StatusDevReady:NEAR
342 extrn CmdErr:NEAR
343 ELSE
344
345 assume ds:NOTHING,es:NOTHING
346
347 StatusDevReady:
348 mov ah,00000011b ; device busy
349 jmp short errEx
350
351 CmdErr:
352 mov al,3 ; Unknown command Error
353 StatusError:
354 mov ah,10000001b
355 jmp short errEx
356
357 ExitP proc far
358 StatusComplete: mov ah,00000001b
359 errEx: pop bx
360 pop es
361
362 mov word ptr es:[bx].STATUS,ax ; put status out
363
364 pop ds
365 pop bp
366 pop di
367 pop si
368 pop dx
369 pop cx
370 pop ax
371 ret
372 ExitP endp
373
374 ENDIF ;INBIOS
375
376
377 subttl Break - Break interrupt routine
378 page
379
380 ;------------------------------------------------------------------------
381 ; Break interrupt routine
382 ;
383
384 assume ds:NOTHING,es:NOTHING
385
386 Break PROC NEAR
387 int 32H ; save registers
388 cli ; ints should be off, make sure!
389 mov ax,RomData
390 mov ds,ax
391 assume ds:RomData
392 mov ax,offset RomData:KeyBuffer
393 mov [BufferHead],ax
394 mov [BufferTail],ax
395 assume ds:NOTHING
396 mov ax,3 ; send char to system
397 mov dx,5 ; ConsInputFilter subfunction
398 call [DosFunction]
399 jz brk1 ; key was eaten by system
400 mov [AltAH],al ; force a ^C
401 brk1:
402 iret
403 Break ENDP
404
405 SUBTTL Keyboard interrupt routine
406 PAGE
407 ; Replacement for ROM keyboard interrupt, tacks on the front.
408 ; OldKeyInterrupt is set to original contents of INT 09H.
409 ; The input character is passed to the O.S. console input filter
410 ; to determine if any special action should be taken. The filter
411 ; return value indicates if the character should be saved in the
412 ; type ahead buffer or if it should be discarded. A keyboard
413 ; semaphore exists to indicate if a process is waiting for input.
414 ; If the keboard semaphore is set all of the processes sleeping on
415 ; it are woken up.
416
417 OldKeyInterrupt DD ?
418 KeySem db 0 ; non-zero if someone waiting on input
419
420 KeyboardInterrupt PROC FAR
421 INT 32H ; Save regs
422 MOV AX,RomData
423 MOV DS,AX
424 ASSUME DS:RomData
425
426 PUSHF ; Save flags to simulate INT
427 CALL CS:OldKeyInterrupt ; Now do ROM code
428 ; Now tell DOS keyboard had char
429 cli ; interrupts off!
430 mov bx,BufferTail ; Get tail of queue
431 cmp bx,BufferHead ; Anything in keyboard queue?
432 JE NoKey ; No, don't requeue then
433 dec bx
434 dec bx
435 cmp bx,offset RomData:KeyBuffer
436 jae kbi1 ; no wrap around in buffer
437 mov bx,offset RomData:KeyBuffer+(KeyBufLen-2)
438 kbi1:
439 mov ax,[bx] ; get last queued char.
440 mov dx,5 ; ConsInputFilter subfunction
441 call [DosFunction]
442 jnz kbi2 ; key should remain in buffer
443 mov BufferTail,bx ; discard key from buffer
444 jmp SHORT NoKey
445 kbi2:
446 cli
447 CMP KeySem,0 ; Outstanding request?
448 JE NoKey ; No, may not be inited either
449 push ax
450 push bx
451 push cx
452 push dx
453 mov ax,cs
454 mov bx,OFFSET KeySem
455 mov cs:byte ptr [bx],0 ; reset keyboard semaphore
456 mov dx,10 ;; ProcRun
457 call [DosFunction] ; awaken anyone waiting on input
458 pop dx
459 pop cx
460 pop bx
461 pop ax
462 NoKey:
463 IRET
464 KeyBoardInterrupt ENDP
465
466 ;-------------------------------------------------------------
467 ; Keyboard INT 16 intercept routine to allow console input to sleep.
468 ; Only console input function 1 is intercepted, all other functions
469 ; are allowed to go directly to the ROM BIOS. For the function 1
470 ; the input status is checked, if a character is ready the function
471 ; is allowed to go to the ROM BIOS. Otherwise the keyboard semaphore
472 ; is set and the process is put to sleep on the address of the
473 ; semaphore. When a key is typed the keyboard interrupt routine
474 ; will wakeup any processes sleeping on this semaphore.
475 ;
476 ; WARNING: The following routines can be entered recursively
477 ; due to the fact that the ROM BIOS routines called
478 ; reenable interrupts. It's not usually a problem
479 ; since interrupts will generally be processed faster
480 ; than anyone can type.
481
482 OldKbdHandler dd ?
483 ScrnIoOk dd ?
484
485 ;-------------------------------------------------------------
486
487 KeyBoardHandler proc far
488 or ah,ah
489 je DoLocalRead
490 cmp ah,1
491 je DoLocalStat
492 OldKBint:
493 jmp [OldKbdHandler]
494
495 DoLocalStat:
496 push bx
497 push ds
498 lds bx,ScrnIoOk
499 test byte ptr [bx],0FFh
500 pop ds
501 pop bx
502 jnz OldKBint
503 xor ax,ax
504 ret 2
505 DoInt16 LABEL FAR ; entry for ChrIn
506 DoLocalRead:
507 push ax
508 push bx
509 push cx
510 push dx
511 DoLocalRd1:
512 push ds
513 lds bx,ScrnIoOk
514 mov ax,ds
515 test byte ptr [bx],0FFh
516 pop ds
517 jnz DoLocalRd2
518 xor cx,cx
519 mov dx,9 ;; ProcBlock
520 call [DosFunction] ; sleep until a screen switch
521 jmp DoLocalRd1
522
523 DoLocalRd2:
524 mov ah,1 ; get console status
525 pushf ; simulate INT to old handler
526 cli
527 call [OldKbdHandler]
528 cli ; subfunction 1 unconditionally sets IF
529 jnz LocalRead ; go read character
530 mov ax,cs
531 mov bx,OFFSET KeySem
532 mov cs:byte ptr [bx],0FFh ; set keyboard semaphore
533 xor cx,cx
534 mov dx,9 ;; ProcBlock
535 call [DosFunction] ; sleep until a char is typed
536 jmp DoLocalRd1
537
538 LocalRead:
539 pop dx
540 pop cx
541 pop bx
542 pop ax
543 jmp [OldKbdHandler] ; read the character and return
544
545 KeyBoardHandler endp
546
547
548 subttl $ConRead - Console Input (Read)
549 page
550
551 ;------------------------------------------------------------------------
552 ; Console Input (Read)
553 ;
554 ; entry:
555 ; DS:BX = pointer to Request packet
556 ; ES:DI = Transfer address
557 ; CX = Count
558 ;
559
560 assume ds:NOTHING,es:NOTHING
561
562 $ConRead:
563 and cx,cx
564 jnz jgl2
565 jmp CRExit
566 ; jcxz CRExit ; no chars to read BUGBUG restore
567 jgl2: cld ; make sure!
568 mov dx,word ptr ds:[bx].START ; get screen number
569 cmp dx,(MaxSIB-1) ; valid number?
570 jbe ConRLoop ; yes, do input
571 mov al,0BH ; no, READ FAULT ERROR
572 jmp StatusError
573 ConRLoop:
574 DEBUG 10h,1,<CONR:$x=$x? >,<dx,CurrSc>
575 cmp dx,[CurrSc]
576 je sjp0
577 call GetSIBAdr ; get pointer to the SIB
578 DEBUG 10h,1,<Block read wrong screen >,<>
579 call DoPBlock ; block the process
580 jmp short ConRLoop ; test flag again
581 sjp0:
582 call ChrIn
583 stosb
584 ; loop ConRLoop
585 loop jgl3
586 CRExit: jmp StatusComplete
587
588 jgl3: jmp ConRLoop
589
590 subttl ChrIn - Read a single character In
591 page
592
593 ;------------------------------------------------------------------------
594 ; Read a single character In
595 ;
596 ; exit:
597 ; Character in AL
598 ;
599 ; modifies: AX
600 ;
601
602 assume ds:NOTHING,es:NOTHING
603
604 ChrIn:
605 DEBUG 10h,1,<in.ChrIn >,<>
606 xor ax,ax
607 xchg al,[AltAH] ; Get Character & zero AltAH
608 or al,al ; A char available?
609 jnz KeyRet
610 ;
611 ;--- NOTE: The blocking on read is done at int 16h level
612 ; in IBMBIO. No need to block here.
613 ;
614 DEBUG 10h,1,< con.do.16 >,<>
615 mov ah,0 ; no, do a read call
616 pushf
617 call DoInt16
618 ;; int 16h
619 DEBUG 10h,1,< con.got.$x >,<ax>
620 or ax,ax ; check for non-key after BREAK
621 jnz jgl1
622 jmp chrin
623
624 jgl1: cmp ax,7200h ; CTRL-PRTSC ?
625 jnz sja0
626 mov al,10h ; yes, make it a ctrl-P
627 sja0: or al,al ; special case?
628 jnz KeyRet
629 mov [AltAH],ah
630 KeyRet:
631 ret
632
633
634 subttl $ConRdnd - Console non-destructive Input, no wait
635 page
636
637 ;------------------------------------------------------------------------
638 ; Console non-destructive Input, no wait
639 ;
640 ; entry:
641 ; DS:BX = pointer to Request packet
642 ;
643
644 assume ds:NOTHING,es:NOTHING
645
646 $ConRdnd:
647 mov dx,word ptr ds:[bx].START ; get screen number
648 cmp dx,(MaxSIB-1) ; valid number?
649 jbe sjq0 ; yes, do input
650 mov al,0BH ; no, READ FAULT ERROR
651 jmp StatusError
652 sjq0:
653 DEBUG 10h,1,<CNDR:$x=$x? >,<dx,CurrSc>
654 cmp dx,[CurrSc]
655 IFDEF DEBUGFLG
656 je sjq1
657 jmp ConBus
658 ELSE
659 jne ConBus ; not current screen, no char avail
660 ENDIF
661 ; call GetSIBAdr ; get pointer to the SIB
662 ; call DoPBlock ; block the process
663 ; jmp short sjq0 ; test flag again
664 sjq1:
665 mov al,[AltAH] ; char avail already?
666 or al,al
667 jnz rdExit
668 DEBUG 10h,1,< NRD:do.16 >,<>
669 mov ah,1 ; no, get status
670 int 16h
671 jz ConBus
672 DEBUG 10h,1,< NRD:nonbus $x >,<ax>
673 or ax,ax
674 jnz NotBk ; Check for null after break
675 mov ah,0 ; flush the null
676 int 16h
677 jmp $ConRdnd ; try again
678 ; jmp short $ConRdnd ; try again BUGBUG
679 NotBk:
680 cmp ax,7200h ; CTRL-PRTSC ?
681 jnz rdExit
682 mov al,10h ; yes, make it a ctrl-P
683 rdExit:
684 mov byte ptr ds:[bx].MEDIA,al ; save character
685 DoExit: jmp StatusComplete
686
687 ConBus: DEBUG 10h,1,< ConBus - >,<>
688 jmp StatusDevReady
689
690
691 subttl $ConFlsh - Console Flush Input
692 page
693
694 ;------------------------------------------------------------------------
695 ; Console Flush Input
696 ;
697 ; entry:
698 ; DS:BX = pointer to Request packet
699 ;
700
701 assume ds:NOTHING,es:NOTHING
702
703 $ConFlsh:
704 mov dx,word ptr ds:[bx].START ; get screen number
705 cmp dx,(MaxSIB-1) ; valid number?
706 jbe sjr0 ; yes, do flush
707 mov al,0BH ; no, READ FAULT ERROR
708 jmp StatusError
709 sjr0:
710 cmp dx,[CurrSc]
711 je sjr1
712 call GetSIBAdr ; get pointer to the SIB
713 call DoPBlock ; block the process
714 jmp short sjr0 ; test flag again
715 sjr1:
716 mov [AltAH],0 ; clear side bufer
717 push ds
718 mov ax,RomData
719 mov ds,ax
720 assume ds:RomData
721 cli ; Disable interrupts
722 mov ax,offset RomData:KeyBuffer ; Start of Rom buffer
723 mov [BufferHead],ax
724 mov [BufferTail],ax ; Empty the queue
725 sti
726 pop ds
727 assume ds:NOTHING
728 jmp StatusComplete
729
730
731 subttl $ConWrit - Console Output (Write)
732 page
733
734 ;------------------------------------------------------------------------
735 ; Console Output (Write)
736 ;
737 ; entry:
738 ; DS:BX = pointer to Request packet
739 ; ES:DI = Transfer address
740 ; CX = Count
741 ;
742
743 assume ds:NOTHING,es:NOTHING
744
745 $ConWrit:
746 jcxz CWExit
747 mov dx, word ptr ds:[bx].START ; get screen number
748 cmp dx,(MaxSIB-1) ; valid screen number?
749 jbe sjb0
750 mov al,0AH ; no, write fault error
751 jmp StatusError
752 sjb0: push cs
753 pop ds
754 assume ds:Code
755 mov bx,[CurrSIB]
756
757 ConWLoop:
758 cmp dx,[CurrSc] ; Is it to the current screen?
759 je sjb2 ; yes, do not block
760 call GetSIBAdr ; get pointer to the SIB
761 sjb1: call DoPBlock ; block the process
762 jmp short ConWLoop ; test ALL flags again
763 sjb2:
764 cmp [bx].ctlS,0 ; is the screen frozen?
765 je sjb3
766 mov ax,bx ; AX = [CurrSIB] = [CurrSIB].ctlS !!!!
767 jmp short sjb1 ; yes, block the process
768 sjb3:
769 cmp [SaveFlg],0 ; are we in the middle of a save?
770 je sjb4 ; no, do write
771 mov ax,offset SaveFlg
772 jmp short sjb1 ; yes, block...
773 sjb4:
774 mov al,es:[di] ; get a character
775 inc di
776 call CharOut
777 loop ConWLoop
778 CWExit: jmp StatusComplete
779
780
781 subttl CharOut - Output a character to the screen
782 page
783
784 ;------------------------------------------------------------------------
785 ; Output a character to the screen
786 ;
787 ; entry:
788 ; AL = Character to write
789 ;
790 ; preserves:
791 ; BX, CX, DX, DI, DS & ES
792 ;
793
794 assume ds:NOTHING,es:NOTHING
795
796 IF ANSI
797 include ansi.inc
798 ELSE
799 CharOut:
800 push bx
801 push di
802 mov bx,7
803 mov ah,14
804 int 10h ; Write Character
805 pop di
806 pop bx
807 ret
808 ENDIF
809
810
811 subttl $GenIOCTL - Generic IOCTL
812 page
813
814 ;------------------------------------------------------------------------
815 ; Generic IOCTL
816 ;
817 ; entry:
818 ; DS:BX = pointer to Request packet
819 ;
820
821 ;--- Offsets into the request packet
822 ;*** Check offset are correct
823 FunCode = 14 ; Function Code
824 FunCat = 13 ; Function Category
825 ;***
826 RegSI = 15 ; Contents of SI
827 RegDI = 17 ; Contents of DI
828 DatBuf = 19 ; Pointer to data buffer
829
830 ;--- Code & Category definitions
831 IOC_SC = 03h ;--- Screen Control
832 IOSC_LS = 41h ; Locate SIB
833 IOSC_SS = 42h ; save segment
834 IOSC_RS = 43h ; restore segment
835 IOSC_EI = 44h ; re-enable i/o
836 IOSC_IS = 45h ; initialize screen
837
838 assume ds:NOTHING,es:NOTHING
839
840 $GenIOCTL:
841 cmp byte ptr ds:[bx].FunCode,IOC_SC
842 jne GI_BadCode ; function not suported
843 mov si,word ptr ds:[bx].RegSI
844 mov al,byte ptr ds:[bx].FunCat
845 cmp al,IOSC_LS
846 jne sjc0
847 jmp short do_IOSC_LS
848 sjc0: cmp al,IOSC_SS
849 jne sjc1
850 jmp short do_IOSC_SS
851 sjc1: cmp al,IOSC_RS
852 jne sjc2
853 jmp do_IOSC_RS
854 sjc2: cmp al,IOSC_EI
855 jne sjc3
856 jmp do_IOSC_EI
857 sjc3: cmp al,IOSC_IS
858 jne GI_BadCode
859 jmp do_IOSC_IS
860
861 GI_BadCode:
862 jmp CmdErr ; error exit: Command error
863
864
865 subttl do_IOSC_LS - Locate SIB
866 page
867
868 ;------------------------------------------------------------------------
869 ; Locate SIB
870 ;
871 ; entry:
872 ; SI = SIB Number
873 ; DS:BX = pointer to Request packet
874 ;
875
876 assume ds:NOTHING,es:NOTHING
877
878 do_IOSC_LS:
879 cmp si,(MaxSIB-1) ; index within range?
880 ja BadNum
881 push bx
882 push ds
883 push cs
884 pop ds
885 assume ds:Code
886 cmp si,[CurrSc] ; is it the current screen?
887 je CurrLS
888 mov [CurrSc],si ; no, just switch curr screens
889 mov dx,si ; index
890 call GetSIBAdr ; get pointer to SIB
891 mov [CurrSIB],ax ; save pointer to curr SIB
892 jmp short retLS
893
894 CurrLS:
895 mov [SaveFlg],1 ; Signal we are Saving the screen
896
897 ;*** Only one segment for now
898
899 mov ax,0
900 call GetSegAdr ; on return BX points to segment
901 mov ax,RomData
902 mov es,ax
903 assume es:RomData
904 IF EAGLE
905 mov al,es:[CRT_MODE]
906 xor ah,ah
907 mov si,ax
908 mov ah,ScreenLen[si]
909 xor al,al
910 ELSE
911 mov ax,es:[CRT_LEN]
912 assume es:NOTHING ; not true, but just to be safe
913 ENDIF
914 mov [bx].SizeNeeded,ax ; save size of segment
915 mov ax,dx ; pointer to current SIB
916 retLS:
917 pop ds
918 pop bx
919 assume ds:NOTHING
920 mov word ptr ds:[bx].DatBuf,ax ; offset
921 mov word ptr ds:[bx].DatBuf+2,cs ; segment
922 mov word ptr ds:[bx].RegSI,0 ; operation ok
923 jmp StatusComplete
924
925 BadNum:
926 mov word ptr ds:[bx].RegSI,1 ; bad SIB number error
927 jmp StatusComplete
928
929
930 subttl do_IOSC_SS - Save Segment
931 page
932
933 ;------------------------------------------------------------------------
934 ; Save Segment
935 ;
936 ; entry:
937 ; SI = Segment Index (into the Current SIB)
938 ; DS:BX = pointer to Request packet
939 ;
940
941 assume ds:NOTHING,es:NOTHING
942
943 do_IOSC_SS:
944 cmp si,(MaxSeg-1) ; within range?
945 BadNumJ1:
946 ja BadNum ; no, somebody screwed up...
947 push bx
948 push ds
949 cmp si,0 ; first segment save?
950 jne nfSS ; no, just save screen data
951 ;--- save screen state data
952 push si ; save index
953 mov ax,RomData
954 mov ds,ax ; DS = ROM data area
955 assume ds:RomData
956 mov si,offset RomData:CRT_MODE
957 mov cx,CrtLen ; length of screen state data
958 push cs
959 pop es
960 assume es:Code
961 mov di,[CurrSIB]
962 lea di,[di].xCRT_MODE
963 cld
964 rep movsb ; copy ROM info to SIB area
965 IF ANSI
966 push cs
967 pop ds
968 assume ds:Code
969 mov si,offset AnsiState ; point to ANSI state info
970 mov cx,AnsiSize
971 rep movsb ; save ANSI state info in SIB
972 ENDIF
973 pop si ; restore segment index
974 ;--- save a segment of screen data
975 nfSS:
976 push cs
977 pop ds
978 assume ds:Code
979 mov ax,si
980 call GetSegAdr ; get adress of segment and curr SIB ptr
981 mov cx,[bx].SizeNeeded ; CX = Ammount to transfer
982 shr cx,1 ; words!
983 les di,[bx].MPointer ; ES:DI = Screen save area
984 assume es:NOTHING
985
986 ;*** For now we are using only one segment
987
988 mov si,dx ; SI points to the current SIB
989 mov bx,ColorSc ; assume color card
990 cmp [si].xCRT_MODE,7 ; is this a BW monitor?
991 jne do_save
992 mov bx,MonoSc
993 do_save:
994 IF BLANK
995 mov dx,[si].xADDR_6845 ; point to mode register
996 add dx,4
997 mov al,[si].xCRT_MODE_SET ; and get value
998 and al,NOT 8
999 out dx,al ; turn off video
1000 ENDIF
1001 mov ds,bx ; DS points to apropiate screen area
1002 assume ds:NOTHING
1003 mov si,0
1004 cld
1005 rep movsw ; copy the screen
1006 IF BLANK
1007 or al,8
1008 out dx,al ; turn on video
1009 ENDIF
1010 pop ds
1011 pop bx
1012 mov word ptr ds:[bx].RegSI,0 ; operation ok
1013 jmp StatusComplete
1014
1015
1016 subttl do_IOSC_RS - Restore Segment
1017 page
1018
1019 ;------------------------------------------------------------------------
1020 ; Restore Segment
1021 ;
1022 ; entry:
1023 ; SI = Segment Index (into the Current SIB)
1024 ; DS:BX = pointer to Request packet
1025 ;
1026
1027 assume ds:NOTHING,es:NOTHING
1028
1029 do_IOSC_RS:
1030 cmp si,(MaxSeg-1) ; within range?
1031 ja BadNumJ1 ; no, somebody screwed up...
1032 push bx
1033 push ds
1034 push cs
1035 pop ds
1036 assume ds:Code
1037 cmp si,0 ; first segment save?
1038 jne nfRS ; no, just restore screen data
1039 ;--- restore screen state data
1040 push si ; save index
1041 mov si,[CurrSIB]
1042 push si
1043 lea si,[si].xCRT_MODE
1044 mov ax,RomData
1045 mov es,ax ; ES = ROM data area
1046 assume es:RomData
1047 mov cx,CrtLen ; length of screen state data
1048 mov di,offset RomData:CRT_MODE
1049 cld
1050 rep movsb ; copy ROM info from SIB area
1051 IF ANSI
1052 push es
1053 push cs
1054 pop es
1055 assume es:Code
1056 mov di,offset AnsiState ; point to ANSI state info
1057 mov cx,AnsiSize
1058 rep movsb ; restore ANSI state info from SIB
1059 pop es
1060 assume es:RomData
1061 ENDIF
1062
1063 ;--- Setup new screen state
1064 pop si
1065 mov al,[si].xCRT_MODE
1066 cmp al,7 ; is this the BW monitor?
1067 jne sjd0
1068 mov al,2 ; this is the "real" mode
1069 sjd0:
1070 mov ah,0
1071 int 10h ; set new mode
1072 mov cx,[si].xCURSOR_MODE
1073 mov ah,1
1074 int 10h ; set cursor type
1075 mov dx,[si].xCURSOR_POSN
1076 mov bh,[si].xACTIVE_PAGE
1077 mov ah,2
1078 int 10h ; set cursor position
1079 mov al,[si].xACTIVE_PAGE
1080 mov ah,5
1081 int 10h ; set page #
1082 mov dx,[si].xADDR_6845
1083 add dx,5
1084 mov al,[si].xCRT_PALETTE
1085 out dx,al ; set color port
1086 mov es:CRT_PALETTE,al
1087 pop si ; restore segment index
1088 ;--- restore a segment of screen data
1089 nfRS:
1090 mov ax,si
1091 call GetSegAdr ; get adress of segment
1092 mov cx,[bx].SizeNeeded ; CX = Ammount to transfer
1093 shr cx,1 ; words!
1094 lds si,[bx].MPointer ; DS:SI = Screen save area
1095 assume ds:NOTHING
1096
1097 ;*** For now we are using only one segment
1098
1099 mov di,dx ; DI points to the current SIB
1100 mov bx,ColorSc ; assume color card
1101 cmp cs:[di].xCRT_MODE,7 ; is this a BW monitor?
1102 jne do_rest
1103 mov bx,MonoSc
1104 do_rest:
1105 IF BLANK
1106 mov dx,cs:[di].xADDR_6845 ; point to mode register
1107 add dx,4
1108 mov al,cs:[di].xCRT_MODE_SET ; and get value
1109 and al,NOT 8
1110 out dx,al ; turn off video
1111 ENDIF
1112 mov es,bx ; ES points to apropiate screen area
1113 assume es:NOTHING
1114 mov di,0
1115 cld
1116 rep movsw ; copy the screen
1117 IF BLANK
1118 or al,8
1119 out dx,al ; turn on video
1120 ENDIF
1121
1122 pop ds
1123 assume ds:NOTHING
1124 pop bx
1125 mov word ptr ds:[bx].RegSI,0 ; operation ok
1126 jmp StatusComplete
1127
1128 BadNumJ:
1129 jmp BadNum
1130
1131
1132 subttl do_IOSC_EI - Re-enable i/o
1133 page
1134
1135 ;------------------------------------------------------------------------
1136 ; Re-enable i/o
1137 ;
1138 ; entry:
1139 ; DS:BX = pointer to Request packet
1140 ;
1141
1142 assume ds:NOTHING,es:NOTHING
1143
1144 do_IOSC_EI:
1145 mov [SaveFlg],0 ; Signal we are done Saving the screen
1146 mov ax,offset Code:SaveFlg
1147 call DoPRun ; ProcRun
1148 mov ax,[CurrSIB] ; pointer to current SIB
1149 call DoPRun ; ProcRun any output blocked because
1150 ; screen was not current
1151 jmp StatusComplete
1152
1153
1154 subttl do_IOSC_IS - Initialize Screen
1155 page
1156
1157 ;------------------------------------------------------------------------
1158 ; Initialize Screen
1159 ;
1160 ; entry:
1161 ; SI = SIB Number
1162 ; DS:BX = pointer to Request packet
1163 ;
1164
1165 assume ds:NOTHING,es:NOTHING
1166
1167 do_IOSC_IS:
1168 cmp si,(MaxSIB-1) ; index within range?
1169 ja BadNumJ
1170 push ds
1171 push cs
1172 pop ds
1173 assume ds:Code
1174 mov [CurrSc],si ; switch curr screens
1175 mov dx,si ; index
1176 call GetSIBAdr ; get pointer to SIB
1177 mov [CurrSIB],ax ; save pointer to curr SIB
1178 mov si,ax
1179 mov [si].ctlS,0 ; screen not frozen
1180 ;--- set screen mode to pc mode 3 (80x25 BW)
1181 mov ax,0003 ; Set mode 3
1182 int 10h
1183 pop ds
1184 assume ds:NOTHING
1185 mov word ptr ds:[bx].RegSI,0 ; operation ok
1186 jmp StatusComplete
1187
1188
1189 subttl $ConStop - Stop (freeze) console output
1190 page
1191
1192 ;------------------------------------------------------------------------
1193 ; Stop (freeze) console output
1194 ;
1195
1196 assume ds:NOTHING,es:NOTHING
1197
1198 $ConStop:
1199 mov bx,[CurrSIB] ; pointer to current SIB
1200 mov cs:[bx].ctlS,01 ; set the freeze flag
1201 jmp StatusComplete
1202
1203
1204 subttl $ConStart - Start (continue) console output
1205 page
1206
1207 ;------------------------------------------------------------------------
1208 ; Start (continue) console output
1209 ;
1210
1211 assume ds:NOTHING,es:NOTHING
1212
1213 $ConStart:
1214 mov bx,[CurrSIB] ; pointer to current SIB
1215 cmp cs:[bx].ctlS,0 ; is it already going?
1216 je csRet ; yes, no need to re-enable
1217 mov cs:[bx].ctlS,0 ; reset the freeze flag
1218 lea ax,[bx].ctlS ; get address of current ctlS
1219 call DoPRun ; do ProcRun
1220 csRet: jmp StatusComplete
1221
1222
1223 subttl DoPBlock - Block the current process
1224 page
1225
1226 ;------------------------------------------------------------------------
1227 ; Block the current process
1228 ;
1229 ; entry:
1230 ; CS:AX = address to block on
1231 ;
1232 ; modifies: AX, FLAGS
1233 ;
1234
1235 assume ds:NOTHING,es:NOTHING
1236
1237 DoPBlock:
1238 push bx
1239 push cx
1240 push dx
1241 mov bx,ax
1242 mov ax,cs ; AX:BX = event identifier
1243 xor cx,cx ; No timeout
1244 ;; mov dx,0109h ;;BUGBUG - should be interruptible wait; will
1245 ;; give InternalError (SchedFind - not on Q)
1246 mov dx,0009h ; PROCBLOC function
1247 cli ; No races!
1248 call [DosFunction]
1249 pop dx ; on return ints are back on
1250 pop cx
1251 pop bx
1252 ret
1253
1254
1255 subttl DoPRun - Restart a process
1256 page
1257
1258 ;------------------------------------------------------------------------
1259 ; Restart a process
1260 ;
1261 ; entry:
1262 ; CS:AX = address to signal on (same as blocked on)
1263 ;
1264 ; modifies: AX, FLAGS
1265 ;
1266
1267 assume ds:NOTHING,es:NOTHING
1268
1269 DoPRun:
1270 push bx
1271 push cx
1272 push dx
1273 mov bx,ax
1274 mov ax,cs
1275 mov dx,10 ; PROCRUN function
1276 call [DosFunction]
1277 pop dx
1278 pop cx
1279 pop bx
1280 ret
1281
1282
1283 subttl GetSIBAdr - Return SIB address
1284 page
1285
1286 ;------------------------------------------------------------------------
1287 ; Returns the adress of the specified SIB
1288 ;
1289 ; entry:
1290 ; DX = index to the SIB
1291 ;
1292 ; exit:
1293 ; AX = pointer to the SIB
1294 ;
1295 ; preserves: ALL
1296 ;
1297
1298 assume ds:Code,es:NOTHING
1299
1300 GetSIBAdr:
1301 push dx ; save screen #
1302 mov ax,dx ; index
1303 mov dx,(SIZE SIBst)
1304 mul dx ; multiply by size of SIB entry
1305 pop dx ; restore screen #
1306 add ax,offset SIB ; AX = pointer to SIB for the write
1307 ret
1308
1309
1310 subttl GetSegAdr - Return segment address
1311 page
1312
1313 ;------------------------------------------------------------------------
1314 ; Returns the adress of a segment in the current SIB
1315 ;
1316 ; entry:
1317 ; AX = index to the segment
1318 ;
1319 ; exit:
1320 ; BX = pointer to the segment
1321 ; DX = pointer to the Current SIB
1322 ;
1323
1324 assume ds:Code,es:NOTHING
1325
1326 GetSegAdr:
1327 mov dx,(SIZE SEGst)
1328 mul dx ; multiply by size of SEG entry
1329 mov bx,[CurrSIB] ; pointer to SIB
1330 mov dx,bx ; save for exit
1331 mov bx,[bx].OffsetVal ; pointer to start of SEGs in SIB
1332 add bx,ax ; BX = pointer to SEG from start of SIB
1333 add bx,dx ; BX = absolute pointer to SEG to use
1334 ret
1335
1336 ifdef DEBUGFLG
1337 if NOT INBIOS
1338 INCLUDE BUGCODE.INC
1339 endif
1340 endif
1341
1342
1343 subttl $ConInit - Initialization Routine
1344 page
1345
1346 ;------------------------------------------------------------------------
1347 ; Initialization Routine
1348 ;
1349 ;entry:
1350 ; DS:BX = pointer to Request packet
1351 ; ES:DI = Dos Functions entry point address
1352 ;
1353
1354 assume ds:NOTHING,es:NOTHING
1355
1356 $ConInit:
1357 IF NOT INBIOS
1358 push ds ; print greeting
1359 push cs
1360 pop ds
1361 mov dx,offset Intro
1362 MOV ah,9
1363 int 21h
1364 pop ds
1365 mov word ptr ds:[bx].TRANS, offset $ConInit
1366 mov word ptr ds:[bx].TRANS+2,cs
1367 ENDIF
1368 mov cs:Word Ptr DosFunction,di ; Save pointer to service routines
1369 mov cs:Word Ptr DosFunction+2,es
1370
1371 mov ax,0
1372 mov cx,1
1373 mov dx,16
1374 call [DosFunction] ; get DOS variable ScrnIoOk
1375 mov word ptr ScrnIoOk,ax
1376 mov word ptr ScrnIoOk+2,dx
1377
1378 ;* Initialize interrupt vectors.
1379 ;;BUGBUG - we should be using Get/Set_Interrupt_Vector calls
1380
1381 xor ax,ax ; initialize break interrupt handler
1382 mov es,ax ; points to page 0
1383 mov ax,cs
1384 mov word ptr es:BRKADR,offset Break
1385 mov word ptr es:BRKADR+2,ax ; Vector for Break
1386
1387 MOV DI,9*4 ; INT 9 - Keyboard interrupt vector
1388 MOV CX,es:[DI] ; Save old addr to hook to
1389 MOV WORD PTR OldKeyInterrupt,CX
1390 MOV CX,es:2[DI]
1391 MOV WORD PTR (OldKeyInterrupt+2),CX
1392 MOV CX,OFFSET KeyboardInterrupt
1393 XCHG AX,CX
1394 STOSW
1395 XCHG AX,CX
1396 STOSW ; Set new keyboard interrupt
1397
1398 mov di,16h*4 ; INT 16 - keyboard input
1399 MOV CX,es:[DI] ; Save INT 16 addr to hook to
1400 MOV WORD PTR OldKbdHandler,CX
1401 MOV CX,es:2[DI]
1402 MOV WORD PTR (OldKbdHandler+2),CX
1403 MOV CX,OFFSET KeyboardHandler
1404 XCHG AX,CX
1405 STOSW
1406 XCHG AX,CX ; Set new keyboard Handler
1407 STOSW
1408 jmp StatusComplete
1409
1410
1411 IF INBIOS
1412 Code ends
1413
1414 BiosInit segment para public 'CODE'
1415 ENDIF
1416
1417 Intro db "--- Installing MTCON Device Driver V"
1418 db CVERS+"0",".",CREV/10+"0"
1419 db (CREV-CREV/10*10)+"0"," ---"
1420 db 13,10,"$"
1421
1422 BiosInit ends
1423
1424 END