summaryrefslogtreecommitdiff
path: root/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM')
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM2214
1 files changed, 2214 insertions, 0 deletions
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM b/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM
new file mode 100644
index 0000000..318b1b0
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM
@@ -0,0 +1,2214 @@
1TITLE IBMBIO IBM BIOS FOR MS-DOS 4.0
2
3; Modified for 3.0, July '83, Marc McDonald
4;
5; arw 02/01/84
6; split disk driver into separate file
7; arw 05/01/84
8; split out console driver
9
10;::::::::::::::::::::::::::::::::::::::::::::::
11;
12; IBM ADDRESSES FOR I/O
13;
14;::::::::::::::::::::::::::::::::::::::::::::::
15
16 PAGE ,132
17;DEBUGFLG = 1 ; don't enable debug printfs
18CONSFLAG = 0 ; =1 to include console driver here
19
20.xlist
21 INCLUDE DEFDBUG.INC
22.list
23
24 BIOSEG=70H ;0070 SEGMENT FOR THE BIOS
25 SYSIZE=100H ;Number of paragraphs in sysinit module
26 RSINIT=0A3H ;RS232 INITIALIZATION
27 ;9600 BAUD:NO PARITY:1 STOP:8 BIT WORD
28 LF=10 ;LINE FEED
29 CR=13 ;CARRIAGE RETURN
30 BACKSP=8 ;BACKSPACE
31 BRKADR=6CH ;006C BREAK VECTOR ADDRESS
32 DSKADR=1EH*4 ;ADDRESS OF PTR TO DISK PARAMETERS
33 SEC9=522H ;ADDRESS OF DISK PARAMETERS
34 AKPORT=20H
35 EOI=20H
36
37
38;** Timer and Clock Definitions
39
40SCHEDCOUNT EQU 50 ; # msec/scheduler tick
41MOTORCOUNT EQU 55 ; # msec/ROM BIOS tick
42
43 EXTRN CURRENT_DOS_LOCATION:WORD
44 EXTRN FINAL_DOS_LOCATION:WORD
45 EXTRN DEVICE_LIST:DWORD
46 EXTRN MEMORY_SIZE:WORD
47 EXTRN DEFAULT_DRIVE:BYTE
48 EXTRN SYSINIT:FAR
49
50BiosSeg GROUP Code,BiosInit
51Code SEGMENT BYTE PUBLIC 'CODE'
52
53 ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING
54
55START$:
56 JMP INIT
57
58 DB 20 DUP (0) ; IBM WANTS SOME ZEROED AREA
59
60SUBTTL Jump tables for devices
61 ;--------------------------------------------------------------
62;
63; COMMAND JUMP TABLES
64;
65; BEWARE - These tables overlap somewhat! -c.p.
66;
67IF CONSFLAG
68CONTBL:
69 DW SetAddr
70 DW StatusComplete
71 DW StatusComplete
72 DW CMDERR
73 DW CON$READ
74 DW CON$RDND
75 DW StatusComplete
76 DW CON$FLSH
77 DW CON$WRIT
78 DW CON$WRIT
79 DW CMDERR
80 DW CMDERR
81 DW CMDERR
82 DW CMDERR
83 DW CMDERR
84 DW CMDERR
85 DW CMDERR
86 DW CMDERR
87 DW CMDERR
88 DW CMDERR
89 DW CMDERR
90 DW CMDERR
91ENDIF ;CONSFLAG
92
93AUXTBL:
94 DW StatusComplete
95 DW StatusComplete
96 DW StatusComplete
97 DW CMDERR
98 DW AUX$READ
99 DW AUX$RDND
100 DW StatusComplete
101 DW AUX$FLSH
102 DW AUX$WRIT
103 DW AUX$WRIT
104 DW AUX$WRST
105 DW CMDERR
106 DW CMDERR
107 DW CMDERR
108 DW CMDERR
109 DW CMDERR
110 DW CMDERR
111 DW CMDERR
112 DW CMDERR
113 DW CMDERR
114 DW CMDERR
115 DW CMDERR
116
117TIMTBL:
118 DW StatusComplete
119 DW StatusComplete
120 DW StatusComplete
121 DW CMDERR
122 DW TIM$READ
123 DW StatusDevReady
124 DW StatusComplete
125 DW StatusComplete
126 DW TIM$WRIT
127 DW TIM$WRIT
128
129PRNTBL:
130 DW StatusComplete
131 DW StatusComplete
132 DW StatusComplete
133 DW CMDERR
134 DW StatusNoXfer ; Printer doesn't read
135 DW StatusDevReady
136 DW StatusComplete
137 DW StatusComplete
138 DW PRN$WRIT
139 DW PRN$WRIT
140 DW PRN$STAT
141 DW StatusComplete
142 DW CMDERR
143 DW CMDERR
144 DW CMDERR
145 DW CMDERR
146 DW CMDERR
147 DW CMDERR
148 DW CMDERR
149 DW CMDERR
150 DW CMDERR
151 DW CMDERR
152
153SUBTTL Device entry points
154 ;---------------------------------------------------
155;
156; Device Entry point
157;
158CMDLEN = 0 ;LENGTH OF THIS COMMAND
159UNIT = 1 ;SUB UNIT SPECIFIER
160CMD = 2 ;COMMAND CODE
161STATUS = 3 ;STATUS
162MEDIA = 13 ;MEDIA DESCRIPTOR
163TRANS = 14 ;TRANSFER ADDRESS
164Dfun = DWORD PTR 14 ; Passed addr of dos function
165COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS
166START = 20 ;FIRST BLOCK TO TRANSFER
167
168AUXNUM DB 0 ;WHICH AUX DEVICE WAS REQUESTED
169
170; Dos routine to do functions for device drivers
171 PUBLIC DosFunction
172DosFunction DD 0 ; Device help function entry point
173ScrnIOok dd 0 ; (char *) true if in current screen locus
174
175TIM_DRV DB -1 ; TIME WHEN LAST DISK I/O PERFORMED
176TIM_REM DW 0 ; scheduler tics left until media presumed
177 ; changed
178
179;** Debugging control:
180;
181; Group Level Controls
182; 01 General BIOS, bootstrapping and initialization
183; 01 Device initialization
184; 02 MS-DOS bootstrapping
185; 04 Driver error conditions
186; 10 Command dispatch
187; 04 Diskette driver
188; 01 Initialization
189; 02 System entrys
190; 04 Details of read/write processing
191; 08 Hard disk driver
192; 01 Initialization
193; 02 System entrys
194; 10 Console display driver
195
196
197 PUBLIC BUGBITS
198BUGBITS DB 000H ; group bits
199 DB 0ffH ; level bits
200
201Strategy PROC FAR
202 RET
203Strategy ENDP
204
205IF CONSFLAG
206CON$IN:
207 PUSH SI
208 MOV SI,OFFSET CONTBL
209 JMP SHORT Interrupt
210ENDIF ;CONSFLAG
211
212AUX0$IN:
213 PUSH SI
214 PUSH AX
215 XOR AL,AL
216 JMP SHORT AUXENT
217
218AUX1$IN:
219 PUSH SI
220 PUSH AX
221 MOV AL,1
222AUXENT:
223 MOV SI,OFFSET AUXTBL
224 JMP SHORT entry1
225
226PRN0$IN:
227 PUSH SI
228 PUSH AX
229 XOR AL,AL
230 JMP SHORT PRNENT
231
232PRN1$IN:
233 PUSH SI
234 PUSH AX
235 MOV AL,1
236 JMP SHORT PRNENT
237
238PRN2$IN:
239 PUSH SI
240 PUSH AX
241 MOV AL,2
242PRNENT:
243 MOV SI,OFFSET PRNTBL
244 JMP SHORT entry1
245
246TIM$IN:
247 PUSH SI
248 MOV SI,OFFSET TIMTBL
249
250
251COMMENT *
252 Interrupt is the main part of the interrupt device entry point( a
253misnomer, actually is the execute function entry ) for all devices.
254The various devices set up the dispatch table address and unit choice
255and then jump to Interrupt which then dispatches to the appropriate
256device routine.
257
258Entry parameters:
259 SI Address of device dispatch table
260 AL Unit # for Aux/Prn( stored in AuxNum )
261 ES:BX Device request packet address
262
263Exit parameters: ( to device routine )
264 AL Unit code from packet
265 AH Media descriptor from packet
266 CX Count from packet
267 DX Start sector from packet
268 ES:DI Buffer address from packet
269 DS:BX Packet address
270 SS TaskArea segment( from dos call )
271 *
272
273 PUBLIC Interrupt
274Interrupt PROC FAR
275 PUSH AX
276entry1:
277 PUSH CX
278 PUSH DX
279 PUSH DI
280 PUSH BP
281 PUSH DS
282 PUSH ES
283 PUSH BX
284 debug 1,10H,< INTERRUPT cmdtbl $x >,<si>
285 MOV CS:[AUXNUM],AL ; Save unit choice of AUX/PRN
286 MOV AX,ES
287 MOV DS,AX ; DS:BX also points to packet
288
289 MOV AL,DS:[BX].Cmd ; Get device command
290 XOR AH,AH
291 ADD SI,AX
292 ADD SI,AX ; Get Address of routine
293 CMP AL,18 ; Too high a command number?
294 JA CmdErr ; Yes, error
295 MOV AL,DS:[BX].UNIT ;AL = Unit code
296 MOV AH,DS:[BX].MEDIA ;AH = Media descriptor
297 MOV CX,DS:[BX].COUNT ;CX = Count
298 MOV DX,DS:[BX].START ;DX = Start sector
299 LES DI,DS:[BX].TRANS ; ES:DI = buffer addr
300 debug 1,10H,<un $x xfer $x:$x rtn $x\n>,<ax,es,di,cs:[si]>
301 JMP WORD PTR CS:[SI] ; Do request
302Interrupt ENDP
303
304SUBTTL Routines used by device routines
305 COMMENT *
306 All routines on this page are various exits for device functions.
307They each return different information in the request packet for the
308dos. The routines are as follows:
309
310 StatusDevReady
311 The busy and done bits are set in the packet. This
312 means that the device has input to be read or can
313 do output without any waiting.
314
315 StatusPartialXfer
316 The device was unable to do the I/O for the requested
317 number of bytes/blocks. CX contains the number that are
318 left to do. Fall into StatusError to set error has
319 happened.
320
321 StatusError
322 Set the error and done bits in the status.
323
324 StatusNoXfer
325 The device couldn't do the read or write, set the
326 number of bytes transferred to 0, but don't set the
327 error bit.
328
329 StatusComplete
330 The device actually completed the request and every-
331 thing was just fine, so just set the done bit in the
332 request status.
333
334 StatusWait
335 The device driver is for 3.0 and saw that it would
336 have to wait in a loop to do the request, so instead
337 it will not set the done bit which tells the dos to
338 put the task into the I/O wait queue.
339
340Entry parameters: ( for all of the above routines )
341 DS:BX Address of device request packet
342 CX Count of bytes/blocks left to transfer if applicable
343 AL Error code if applicable
344
345Exit parameters:
346 ES:BX Pointer to packet
347 AX Destroyed
348 SI Destroyed
349 All other registers preserved
350 *
351
352 PUBLIC StatusDevReady
353StatusDevReady PROC NEAR ; Device has data or can send
354 MOV AH,00000011B ; Done + busy
355 JMP SHORT SetStatus
356StatusDevReady ENDP
357
358 PUBLIC CmdErr
359CmdErr PROC NEAR ; Bad device command number
360 debug 1,4,< CMDERR - $b $x\n>,<ax,si>
361 MOV AL,3 ; Unknown command error
362CmdErr ENDP
363
364StatusPartialXfer PROC NEAR
365 SUB [BX].COUNT,CX ;# of successful I/O's
366StatusPartialXfer ENDP
367
368 PUBLIC StatusError
369StatusError PROC NEAR
370 MOV AH,10000001B ; Error + done
371 JMP SHORT SetStatus
372StatusError ENDP
373
374StatusNoXfer PROC NEAR
375 XOR AX,AX
376 MOV [BX].COUNT,AX ; No chars read
377StatusNoXfer ENDP
378
379 PUBLIC StatusComplete
380StatusComplete PROC NEAR
381 MOV AH,00000001B ; Done
382 PUBLIC SetStatus
383SetStatus:
384 POP BX
385 POP ES
386 MOV ES:WORD PTR [BX].STATUS,AX ;MARK OPERATION COMPLETE
387 POP DS
388 POP BP
389 POP DI
390 POP DX
391 POP CX
392 POP AX
393 POP SI
394XXX PROC FAR
395 RET ;RESTORE REGS AND RETURN
396XXX ENDP
397StatusComplete ENDP
398
399StatusWait PROC NEAR
400 MOV AH,0 ; Don't set done bit
401 MOV [BX].Count,CX ; Set number completed
402 MOV WORD PTR [BX].Trans,DI ; Set new offset
403 JMP SetStatus
404StatusWait ENDP
405
406IF CONSFLAG
407; Set the address of the dos function routine for drivers
408SetAddr PROC NEAR
409 MOV AX,WORD PTR [BX].Dfun
410 MOV WORD PTR DosFunction,AX
411 MOV AX,WORD PTR [BX+2].Dfun
412 MOV WORD PTR (DosFunction+2),AX
413 mov ax,0
414 mov cx,1
415 mov dx,16
416 call DosFunction
417 mov word ptr ScrnIOok,ax
418 mov word ptr ScrnIOok+2,dx
419 JMP StatusComplete
420SetAddr ENDP
421
422
423;-------------------------------------------------------------
424;
425; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE
426;
427; CALLED VIA INT 29H
428;
429CHROUT = 29H
430
431OUTCHR: STI
432 PUSH AX
433 MOV BX,7
434 MOV AH,14 ;WRITE CHARACTER
435 INT 10H ;SEND THE CHARACTER
436 POP AX
437 IRET
438ENDIF ;CONSFLAG
439
440;----------------------------------------------
441;
442; SET DX TO AUXNUM
443;
444GETDX: MOV DL,[AUXNUM]
445 XOR DH,DH
446 RET
447
448SUBTTL Console driver
449 COMMENT *
450 This is the console( CON ) device driver. The input side is assigned
451to the keyboard and the output to the video screen. The output code
452remains more or less the same as in 2.0. The input side, however, is
453changed for 4.0 to enter an I/O wait rather than loop waiting for a
454character.
455 *
456
457IF CONSFLAG
458CONDEV LABEL WORD ;HEADER FOR DEVICE "CON"
459 DW AUXDEV,BIOSEG
460 DW 1000000000010011B ;CON IN AND CON OUT + SPECIAL
461 DW STRATEGY
462 DW CON$IN
463 DB 'CON '
464ELSE
465 EXTRN CONDEV:NEAR
466 PUBLIC AUXDEV
467ENDIF ;CONSFLAG
468
469IF CONSFLAG
470Key2ndPart DB 0 ; Leftover byte of 2 key codes
471
472RomData SEGMENT AT 40H
473 ORG 1AH
474Bufferhead DW ?
475BufferTail DW ?
476KeyBuffer LABEL WORD
477KeyBufLen equ 32 ; length of KeyBuffer
478RomData ENDS
479
480; BREAK interrupt routine
481; ROM interrupt handler resets buffer pointers to beginning of buffer
482; and places a 0000h dummy character into the buffer.
483
484Break PROC NEAR
485 mov Key2ndPart,3 ; Force next char to be ^C( stop )
486 IRET
487Break ENDP
488
489SUBTTL Console read and subroutines
490 PAGE
491
492COMMENT *
493 The console read dispatch tries to read the selected number of
494characters from the keyboard. If at any point there is no key in
495the queue, it returns to the dos to allow another process to run
496until a key is depressed.
497
498Entry parameters:
499 ES:DI Pointer to buffer in which to store characters
500 CX Number of characters to read
501 DS:BX Pointer to device request packet
502
503Exit parameters:
504 CX Number of characters left to read
505 DS:BX Pointer to device request packet
506 *
507
508Con$Read PROC NEAR
509 JCXZ StatusComplete
510CON$LOOP:
511 PUSH CX ;SAVE COUNT
512 CALL ChrIn ;GET CHAR IN AL
513 POP CX
514 STOSB ;STORE CHAR AT ES:DI
515 LOOP CON$LOOP
516 JMP StatusComplete
517Con$Read ENDP
518
519COMMENT *
520 ChrIn attempts to read a character from the keyboard queue that
521is maintained by the ROM BIOS. If the queue is not empty, the code
522is returned. Otherwise, the packet is added to the list of keyboard
523reads and carry is set to cause the driver routine to return to the
524dos with the done bit not set which results in an I/O wait.
525
526Entry parameters:
527 DS:BX Pointer to device request packet
528
529Exit parameters:
530 AL Character from keyboard if present
531*
532
533ChrIn PROC NEAR
534ConReadLoop:
535 XOR AX,AX
536 XCHG AL,Key2ndPart ; GET CHARACTER & ZERO Key2ndPart
537 OR AL,AL
538 JNZ KeyRet
539 MOV AH,0
540 INT 16H ; Get the char
541 OR AX,AX ;Check for non-key after BREAK
542 JZ ConReadLoop
543 CMP AX,7200H ;Check for CTRL-PRTSC
544 JNZ ALT15
545 MOV AL,16
546ALT15:
547 OR AL,AL ; 2 byte keycode?
548 JNZ KeyRet ; No, have whole code
549 MOV Key2ndPart,AH ; Yes, store scan code for next read
550KeyRet: RET
551ChrIn ENDP
552
553
554COMMENT *
555 The non-destructive keyboard read routine returns the next char
556in the queue if there is one.
557
558Entry parameters:
559 DS:BX Pointer to device request packet
560
561Exit parameters:
562 DS:BX Pointer to device request packet
563 *
564Con$RdNd PROC NEAR
565 MOV AL,[Key2ndPart]
566 OR AL,AL
567 JNZ RDexit
568 mov ah,1
569 int 16h
570 JZ CONBUS
571 OR AX,AX
572 JNZ NOTBRK ;CHECK FOR NULL AFTER BREAK
573 MOV AH,0
574 INT 16H ;READ THE NULL
575 JMP CON$RDND ;AND GET A REAL STATUS
576NOTBRK: CMP AX,7200H ;CHECK FOR CTRL-PRTSC
577 JNZ RDexit
578 MOV AL,16
579RDexit:
580 MOV [BX].MEDIA,AL
581EXVEC: JMP StatusComplete
582CONBUS: JMP StatusDevReady
583Con$RdNd ENDP
584
585;--------------------------------------------------------------
586;
587; KEYBOARD FLUSH ROUTINE
588;
589Con$Flsh PROC NEAR
590 MOV [Key2ndPart],0 ;Clear out holding buffer
591
592 CALL Flush ; Flush the keyboard
593 JMP EXVEC
594Con$Flsh ENDP
595
596
597Flush PROC NEAR
598 PUSH DS
599 MOV AX,RomData
600 MOV DS,AX
601 ASSUME DS:RomData
602
603 CLI ; ** Disable interrupts
604 MOV AX,offset RomData:KeyBuffer ; Start of Rom buffer
605 MOV BufferHead,AX
606 MOV BufferTail,AX ; Empty the queue
607 STI ; ** enable interrupts
608 POP DS
609 ASSUME DS:NOTHING
610
611 RET
612Flush ENDP
613
614SUBTTL Console output( video ) routines
615 PAGE
616
617;----------------------------------------------------------
618;
619; CONSOLE WRITE ROUTINE
620;
621CON$WRIT:
622 JCXZ EXVEC
623CON$LP: MOV AL,ES:[DI] ;GET CHAR
624 INC DI
625 PUSH CX
626 PUSH DI
627 INT CHROUT ;OUTPUT CHAR
628 POP DI
629 POP CX
630 LOOP CON$LP ;REPEAT UNTIL ALL THROUGH
631 JMP EXVEC
632
633SUBTTL Keyboard interrupt routine
634PAGE
635; Replacement for ROM keyboard interrupt, tacks on the front.
636; OldKeyInterrupt is set to original contents of INT 09H.
637; The input character is passed to the O.S. console input filter
638; to determine if any special action should be taken. The filter
639; return value indicates if the character should be saved in the
640; type ahead buffer or if it should be discarded. A keyboard
641; semaphore exists to indicate if a process is waiting for input.
642; If the keboard semaphore is set all of the processes sleeping on
643; it are woken up.
644
645OldKeyInterrupt DD ?
646KeySem db 0 ; non-zero if someone waiting on input
647
648KeyboardInterrupt PROC FAR
649 INT 32H ; Save regs
650 MOV AX,RomData
651 MOV DS,AX
652 ASSUME DS:RomData
653
654 PUSHF ; Save flags to simulate INT
655 CALL CS:OldKeyInterrupt ; Now do ROM code
656; Now tell scheduler keyboard had char
657 cli ; interrupts off!
658 mov bx,BufferTail ; Get tail of queue
659 cmp bx,BufferHead ; Anything in keyboard queue?
660 JE NoKey ; No, don't requeue then
661 dec bx
662 dec bx
663 cmp bx,offset RomData:KeyBuffer
664 jae kbi1 ; no rap around in buffer
665 mov bx,offset RomData:KeyBuffer+KeyBufLen
666kbi1:
667 mov ax,[bx] ; get last queued char.
668 mov dx,5 ; ConsInputFilter subfunction
669 call DosFunction
670 jnz kbi2 ; key should remain in buffer
671 mov BufferTail,bx ; discard key from buffer
672 jmp SHORT NoKey
673kbi2:
674 cli
675 CMP KeySem,0 ; Outstanding request?
676 JE NoKey ; No, may not be inited either
677 push ax
678 push bx
679 push cx
680 push dx
681 mov ax,cs
682 mov bx,OFFSET KeySem
683 mov cs:byte ptr [bx],0 ; reset keyboard semaphore
684 mov dx,10 ;; ProcRun
685 call [DosFunction] ; awaken anyone waiting on input
686 pop dx
687 pop cx
688 pop bx
689 pop ax
690NoKey:
691 IRET
692KeyBoardInterrupt ENDP
693
694;-------------------------------------------------------------
695; Keyboard INT 16 intercept routine to allow console input to sleep.
696; Only console input function 1 is intercepted, all other functions
697; are allowed to go directly to the ROM BIOS. For the function 1
698; the input status is checked, if a character is ready the function
699; is allowed to go to the ROM BIOS. Otherwise the keyboard semaphore
700; is set and the process is put to sleep on the address of the
701; semaphore. When a key is typed the keyboard interrupt routine
702; will wakeup any processes sleeping on this semaphore.
703;
704; WARNING: The following routines can be entered recursively
705; due to the fact that the ROM BIOS routines called
706; reenable interrupts. It's not usually a problem
707; since interrupts will generally be processed faster
708; than anyone can type.
709
710OldKbdHandler dd ?
711
712;-------------------------------------------------------------
713
714KeyBoardHandler proc far
715 or ah,ah
716 je DoLocalRead
717 cmp ah,1
718 je DoLocalStat
719OldKBint:
720 jmp [OldKbdHandler]
721
722DoLocalStat:
723 push bx
724 push ds
725 lds bx,ScrnIOok
726 test byte ptr [bx],0FFh
727 pop ds
728 pop bx
729 jnz OldKBint
730 xor ax,ax
731 ret 2
732
733DoLocalRead:
734 push ax
735 push bx
736 push cx
737 push dx
738DoLocalRd1:
739 push ds
740 lds bx,ScrnIOok
741 mov ax,ds
742 test byte ptr [bx],0FFh
743 pop ds
744 jnz DoLocalRd2
745 xor cx,cx
746 mov dx,9 ;; ProcBlock
747 call [DosFunction] ; sleep until a char is typed
748 jmp DoLocalRd1
749
750DoLocalRd2:
751 mov ah,1 ; get console status
752 pushf ; simulate INT to old handler
753 cli
754 call [OldKbdHandler]
755 cli ; subfunction 1 unconditionally sets IF
756 jnz LocalRead ; go read character
757 mov ax,cs
758 mov bx,OFFSET KeySem
759 mov cs:byte ptr [bx],0FFh ; set keyboard semaphore
760 xor cx,cx
761 mov dx,9 ;; ProcBlock
762 call [DosFunction] ; sleep until a char is typed
763 jmp DoLocalRd1
764
765LocalRead:
766 pop dx
767 pop cx
768 pop bx
769 pop ax
770 jmp [OldKbdHandler] ; read the character and return
771
772KeyBoardHandler endp
773
774ENDIF ;CONSFLAG
775
776SUBTTL Aux driver
777 ;------------------------------------------------------
778;
779; A U X - AUXILARY DEVICE DRIVER
780;
781AUXDEV LABEL WORD ;HEADER FOR DEVICE "AUX"
782 DW PRNDEV,BIOSEG
783 DW 1000000000000000B
784 DW STRATEGY
785 DW AUX0$IN
786 DB 'AUX '
787
788 PUBLIC COM1DEV
789COM1DEV LABEL WORD
790 DW LPT1DEV,BIOSEG
791 DW 1000000000000000B
792 DW STRATEGY
793 DW AUX0$IN
794 DB 'COM1 '
795
796COM2DEV LABEL WORD
797 DW -1,BIOSEG
798 DW 1000000000000000B
799 DW STRATEGY
800 DW AUX1$IN
801 DB 'COM2 '
802
803AUXBUF DB 0,0
804;-------------------------------------------------------
805;
806; READ FROM AUXILARY DEVICE
807;
808AUX$READ:
809 JCXZ EXVEC2
810 CALL GETBX
811 XOR AX,AX
812 XCHG AL,[BX] ;Get character and zero buffer
813 OR AL,AL
814 JNZ AUX2
815AUX1: CALL AUXIN
816AUX2: STOSB ;STORE CHARACTER
817 LOOP AUX1
818EXVEC2: JMP StatusComplete
819
820AUXIN: MOV AH,2 ;INDICATES A READ
821 CALL AUXOP ;READ THE AUXILIARY PORT
822 TEST AH,0EH ;Check framing, parity, overrun
823 JZ AROK
824 POP AX ;Clean up the stack
825 MOV AL,0BH ;READ ERROR
826 JMP StatusPartialXfer
827AROK: RET
828;--------------------------------------------------------
829;
830; AUX NON-DESTRUCTIVE READ, NO WAITING
831;
832AUX$RDND:
833 CALL GETBX
834 MOV AL,[BX] ;GET KEY AND ZERO BUFFER
835 OR AL,AL
836 JNZ AUXRDX ;KEY IN BUFFER?
837 CALL AUXSTAT
838 TEST AH,00000001B ;TEST DATA READY
839 JZ AUXBUS
840 TEST AL,00100000B ;TEST DATA SET READY
841 JZ AUXBUS
842 CALL AUXIN
843 CALL GETBX
844 MOV [BX],AL ;GET AND SAVE KEY
845AUXRDX: JMP StatusComplete
846AUXBUS: JMP StatusDevReady
847;----------------------------------------------------------
848;
849; AUX OUTPUT STATUS
850;
851AUX$WRST:
852 CALL AUXSTAT
853 TEST AL,00100000B ;TEST DATA SET READY
854 JZ AUXBUS
855 TEST AH,00100000B ;TEST CLEAR TO SEND
856 JZ AUXBUS
857 JMP EXVEC2
858
859AUXSTAT:
860 MOV AH,3
861AUXOP: CALL GETDX
862 INT 14H
863 RET
864;---------------------------------------------------------
865;
866; FLUSH AUX INPUT BUFFER
867;
868AUX$FLSH:
869 CALL GETBX
870 MOV BYTE PTR [BX],0
871 JMP EXVEC2
872;---------------------------------------------------------
873;
874; WRITE TO AUXILARY DEVICE
875;
876AUX$WRIT:
877 JCXZ EXVEC2
878AUX$LOOP:
879 MOV AL,ES:[DI] ;GET CHAR
880 INC DI ;POINT TO NEXT ONE
881 MOV AH,1 ;INDICATES A WRITE
882 CALL AUXOP ;SEND CHARACTER OVER AUX PORT
883 TEST AH,80H ;CHECK FOR ERROR
884 JZ AWOK
885 MOV AL,10 ;INDICATE WRITE FAULT
886 JMP StatusPartialXfer
887AWOK: LOOP AUX$LOOP
888 JMP EXVEC2
889
890GETBX: CALL GETDX
891 MOV BX,DX
892 ADD BX,OFFSET AUXBUF
893 RET
894SUBTTL Printer driver
895 ;-------------------------------------------------------------
896;
897; P R N - PRINTER DEVICE
898;
899PRNDEV LABEL WORD ;HEADER FOR DEVICE "PRN"
900 DW TIMDEV,BIOSEG
901 DW 1000000000000000B
902 DW STRATEGY
903 DW PRN0$IN
904 DB 'PRN '
905
906LPT1DEV LABEL WORD
907 DW LPT2DEV,BIOSEG
908 DW 1000000000000000B
909 DW STRATEGY
910 DW PRN0$IN
911 DB 'LPT1 '
912
913LPT2DEV LABEL WORD
914 DW LPT3DEV,BIOSEG
915 DW 1000000000000000B
916 DW STRATEGY
917 DW PRN1$IN
918 DB 'LPT2 '
919
920LPT3DEV LABEL WORD
921 DW COM2DEV,BIOSEG
922 DW 1000000000000000B
923 DW STRATEGY
924 DW PRN2$IN
925 DB 'LPT3 '
926
927ERRFLG DB 0
928
929;----------------------------------------------------------
930;
931; WRITE TO PRINTER DEVICE
932;
933PRN$WRIT:
934 JCXZ EXVEC3
935PRN$LOOP:
936 MOV AL,ES:[DI] ;GET CHAR INTO AL
937 INC DI ;POINT TO NEXT CHAR
938 MOV [ERRFLG],0 ;INITIALIZE RETRY FLAG
939
940PRETRY: XOR AH,AH ;AH=0
941 CALL PRNOP ;TO INDICATE PRINT CHAR IN AL
942
943ERRCHK: JZ PROK
944 XOR [ERRFLG],1 ;DO 1 AUTOMATIC RETRY
945 JNZ PRETRY
946PMESSG: JMP StatusPartialXfer ;RETURN WITH THE ERROR
947
948PROK: LOOP PRN$LOOP
949EXVEC3: JMP StatusComplete
950;--------------------------------------------------------
951;
952; PRINTER STATUS ROUTINE
953;
954PRN$STAT:
955 CALL PRNSTAT ;DEVICE IN DX
956 JNZ PMESSG
957 TEST AH,10000000B
958 JNZ EXVEC3
959 JMP StatusDevReady
960
961PRNSTAT:
962 MOV AH,2
963PRNOP: CALL GETDX
964 INT 17H
965
966 MOV AL,2
967 TEST AH,0001B ;TEST FOR NOT READY
968 JNZ PRNOP2
969
970 MOV AL,10 ;WRITE FAULT CODE
971 TEST AH,1000B ;TEST FOR I/O ERROR
972 JZ PRNOP2
973
974 TEST AH,00100000B ;OUT-OF-PAPER?
975 JZ PRNOP1
976 MOV AL,9 ;OUT OF PAPER CODE
977PRNOP1: OR AL,AL ;SET NZ FLAG
978PRNOP2: RET
979
980SUBTTL Timer (clock) driver
981 PAGE
982
983;** Time Functions
984;
985; Uses clock with 1000 ticks per second. User sees only
986; time in hours, minutes, seconds, and 1/100 second, in registers
987; CH, CL, DH, DL respectively. (Each is a binary number.)
988; Modified for 4.0. The ROM bios timer routines are completely
989; replaced with code on this page. This provides a better time base
990; for the scheduler.
991
992
993 EXTRN Floppydevice:NEAR
994TIMDEV LABEL WORD
995 DW Floppydevice,BIOSEG
996 DW 1000000000001000B
997 DW STRATEGY
998 DW TIM$IN
999 DB 'CLOCK$ '
1000
1001DAYCNT DW 0
1002
1003;--------------------------------------------------------------------
1004;
1005; Settime sets the current time
1006;
1007; On entry ES:[DI] has the current time:
1008;
1009; number of days since 1-1-80 (WORD)
1010; minutes (0-59) (BYTE)
1011; hours (0-23) (BYTE)
1012; hundredths of seconds (0-99) (BYTE)
1013; seconds (0-59) (BYTE)
1014;
1015; Each number has been checked for the correct range.
1016
1017TIM$WRIT:
1018 PUSH BX
1019 MOV AX,ES:[DI]
1020 MOV DAYCNT,AX
1021 MOV CX,ES:[DI+2]
1022 MOV AL,60
1023 MUL CH ;Hours to minutes
1024 MOV CH,0
1025 ADD AX,CX ;Total minutes
1026 MOV CX,60000 ;60*1000
1027 MUL CX ;Convert to milliseconds
1028 MOV SI,AX
1029 MOV BX,DX ; Save hours, min in Msecs in BX:SI
1030 MOV AL,ES:[DI+5] ; Get # seconds
1031 MOV CX,100
1032 MUL CL ; Get seconds in 1/100s
1033 MOV CL,ES:[DI+4] ; Hundredths of second
1034 ADD AX,CX ; Now have seconds and 1/100ths
1035 MOV CL,10
1036 MUL CX ; Get DX:AX = milliseconds
1037 ADD AX,SI
1038 MOV CS:TickLow,AX
1039 ADC BX,0
1040 MOV CS:TickHigh,BX ; Set time in milliseconds
1041 POP BX
1042 JMP StatusComplete
1043
1044
1045;***************************************
1046;
1047; Gettime reads date and time
1048; and returns the following information:
1049;
1050; ES:[DI] =count of days since 1-1-80
1051; ES:[DI+2]=minutes
1052; ES:[DI+3]=hours
1053; ES:[DI+4]=hundredths of seconds
1054; ES:[DI+5]=seconds
1055;
1056;***************************************
1057 PUBLIC TIM$READ
1058TIM$READ:
1059 PUSH BX
1060 MOV AX,DayCnt
1061 STOSW ; return day
1062 MOV DX,CS:TickHigh
1063 MOV AX,CS:TickLow ; Get current time
1064 MOV CX,60000 ; # milliseconds in a minute
1065 DIV CX ; Get AX= minutes, DX = seconds&msecs
1066 MOV BX,DX ; Save seconds and fraction
1067 XOR DX,DX
1068 MOV CX,60 ; # minutes/hour
1069 DIV CX ; Get AX= hour, DX= minute
1070 xchg ax,dx
1071 STOSB ; Return minutes
1072 xchg ax,dx
1073 STOSB ; Return hours
1074 MOV AX,BX
1075 XOR DX,DX
1076 MOV CX,1000
1077 DIV CX ; Get AX= seconds, DX= milliseconds
1078 xchg ax,bx ; (bx) = seconds
1079 MOV AX,DX
1080 XOR DX,DX
1081 MOV CX,10
1082 DIV CX ; Get hundredths of second
1083 STOSB ; Return hundredths of second
1084 xchg ax,bx
1085 STOSB ; Return second
1086 POP BX
1087 JMP StatusComplete
1088
1089SUBTTL Clock interrupt and replacement for ROM code
1090PAGE
1091
1092COMMENT *
1093 The clock code in the ROM is replaced with the following code which
1094provides the clock interface to the scheduler and a 1 ms time base. The
10951AH interrupt is simulated to return the approximate time for those
1096routines which still call 1AH. The time period for motor start up is
1097preserved since that code has not yet been rewritten.
1098 *
1099
1100RomData SEGMENT AT 040H
1101 ORG 03FH
1102Motor_Status DB 1 DUP(?)
1103Motor_Count DB 1 DUP(?)
1104RomData ENDS
1105
1106TickLow DW ? ; Low part of time in Msec
1107TickHigh DW ? ; High part of time in msec
1108MotorFlag DB 0 ; There is an active motor
1109MotorTick DB MOTORCOUNT ; # ticks until 1/18.2 secs
1110SchedTick DB SCHEDCOUNT ; Scheduler countdown
1111
1112; Interrupt 8H - timer interrupt
1113
1114 ASSUME DS:NOTHING
1115TimerInterrupt PROC FAR
1116 PUSH AX
1117 INC TickLow
1118 JNZ NoOverflow
1119 INC TickHigh
1120NoOverFlow:
1121 CMP TickHigh,1318 ; Close to 24 hours?
1122 JNZ NotDay ; No
1123 CMP TickLow,23552 ; Reach 24 hours?
1124 JNZ NotDay ; No
1125; Have reached a day, bump day count
1126 INC DayCnt
1127 XOR AX,AX
1128 MOV TickHigh,AX
1129 MOV TickLow,AX ; Reset time of day
1130NotDay:
1131;; DEC MotorTick ; Time to decrement motor?
1132;; JNZ CheckSched ; No
1133;; MOV MotorTick,MOTORCOUNT ; Reset 1/18 sec worth of msecs
1134;; PUSH DS
1135;; MOV AX,RomData
1136;; MOV DS,AX
1137;; ASSUME DS:RomData
1138
1139;; TEST MotorFlag,0FFH ; Active motor timer?
1140;; JZ CheckMotor ; No, see if new one
1141;; DEC Motor_Count
1142;; JNZ CheckMotor ; Not time to shut down
1143;; AND Motor_Status,0F0H ; Turn off motor running bits
1144;; MOV AL,0CH
1145;; PUSH DX
1146;; MOV DX,03F2H
1147;; OUT DX,AL ; Turn off the motors
1148;; POP DX
1149;; MOV MotorFlag,0 ; No motor timeout running
1150;; POP DS
1151;; JMP CheckSched ; Go see if time to sched
1152
1153;;CheckMotor:
1154;; MOV AL,Motor_Count
1155;; POP DS
1156;; JNZ CheckSched ; Motor already active
1157;; OR AL,AL ; Need to start countdown?
1158;; JZ CheckSched ; No
1159;; MOV MotorFlag,0FFH ; Yes, set flag
1160;; MOV MotorTick,MOTORCOUNT ; 1/18.2 sec later
1161
1162; The scheduler is called every 10ms, rather than every 1 ms to see if
1163; it should switch tasks.
1164CheckSched:
1165; First reset the timer so will interrupt again
1166 MOV AL,36H
1167 OUT 43H,AL
1168 MOV AL,169
1169 OUT 40H,AL
1170 MOV AL,4
1171 OUT 40H,AL ; Set 1 msec delay
1172 MOV AL,20H
1173 OUT 20H,AL ; Tell 8259 interrupt done
1174; Now see if should call scheduler
1175 DEC SchedTick ; Time to call scheduler?
1176 JNZ NoSched ; No, all done
1177 MOV SchedTick,SCHEDCOUNT ; Reset countdown
1178csch1: POP AX ; Stack is now clean
1179 INT 32H ; Save all regs
1180 CMP WORD PTR (DosFunction+2),0 ; Dos installed?
1181 JE NoSchedActive ; Not yet, don't call sched
1182 sub dx,dx ; (dx) = 0 = tic subfunction
1183 mov ax,SCHEDCOUNT ; 10 milliseconds per tic
1184 CALL DosFunction ; Do the tick
1185 EXTRN FloppyTimer:FAR
1186 CALL FloppyTimer ; timer service for floppy disk also
1187NoSchedActive:
1188 IRET ; All done
1189
1190NoSched:
1191 POP AX
1192INTRET: IRET ; All done
1193TimerInterrupt ENDP
1194
1195; INT 1AH - Get/Set time based in 55msec tick
1196
1197TimeOfDay PROC FAR
1198 OR AH,AH ; Function 0: Read time?
1199 JZ ReadOld ; Yes
1200 DEC AH ; Function 1: Write time?
1201 JZ WriteOld ; Yes
1202 IRET ; No, bad function code
1203
1204; Read old( 1/18.2 second tick ) time
1205ReadOld:
1206 MOV AX,TickHigh
1207 xor dx,dx
1208 MOV CX,MOTORCOUNT ; # milliseconds in 1/18.2 secs
1209 DIV CX ; Get value in old ticks
1210 push ax
1211 MOV AX,TickLow
1212 div cx
1213 pop cx ; get high order count
1214 XOR AL,AL ; Never have oveflow
1215 IRET ; Return the time
1216
1217; Set time using old resolution
1218WriteOld:
1219 MOV AX,DX
1220 push bx
1221 MOV BX,MOTORCOUNT ; Conversion factor
1222 MUL BX
1223 MOV TickLow,AX ; Set low part of time
1224 mov ax,cx
1225 mov cx,dx
1226 MUL BX
1227 pop bx
1228 ADD AX,CX ; Combine high parts
1229 MOV TickHigh,AX ; Set time
1230 IRET ; Return with new time set
1231TimeOfDay ENDP
1232
1233;++++
1234memsizmsg db 13,10,'Error - Interrupt 12',13,10,0
1235memsizint dd 0
1236
1237memsizhandler proc far
1238 push ax
1239 push bx
1240 push si
1241 push ds
1242 push cs
1243 pop ds
1244 mov SI,offset CS:memsizmsg
1245 call WRMSG
1246 pop ds
1247 pop si
1248 pop bx
1249 pop ax
1250 jmp memsizint
1251memsizhandler endp
1252;++++
1253
1254;----------------------------------------------
1255; WRITE OUT MESSAGE POINTED TO BY [SI]
1256;
1257WRMSG: LODSB ;GET THE NEXT CHARACTER OF THE MESSAGE
1258 AND AL,7FH ;SEE IF END OF MESSAGE
1259 JZ WRMRET
1260 MOV BX,7
1261 MOV AH,14 ;WRITE CHARACTER
1262 INT 10H ;SEND THE CHARACTER
1263 JMP SHORT WRMSG
1264WRMRET: RET
1265
1266.xlist
1267 INCLUDE BUGCODE.INC
1268.list
1269
1270Code ENDS
1271
1272SUBTTL Diskette driver -- now used only for bootup
1273 ;-----------------------------------------------------------------
1274;
1275; DISK INTERFACE ROUTINES
1276;
1277BiosInit SEGMENT PARA PUBLIC 'CODE'
1278
1279DRVMAX DB 4
1280
1281 ASSUME CS:BiosSeg
1282
1283MAXERR = 5
1284LSTDRV = 504H
1285
1286WRTVERIFY LABEL WORD
1287RFLAG DB 2 ;2 for read, 3 for write
1288VERIFY DB 0 ;1 if verify after write
1289SINGLE DB 0 ;1 if single drive system
1290SWPFLG DB 0 ;1 if BIOS swapped out
1291SECCNT DW 0
1292HARDNUM DB 99 ;logical drive number of first hardfile
1293
1294RESSEC = 3
1295DRVLIM = 8 ;Number of sectors on device
1296SECLIM = 13 ;MAXIMUM SECTOR
1297HDLIM = 15 ;MAXIMUM HEAD
1298HIDSEC = 17 ;NUMBER OF HIDDEN SECTORS
1299
1300;WARNING - preserve order of drive and curhd! -c.p.
1301
1302DRIVE DB 0 ;PHYSICAL DRIVE CODE
1303CURHD DB 0 ;CURRENT HEAD
1304CURSEC DB 0 ;CURRENT SECTOR
1305CURTRK DW 0 ;CURRENT TRACK
1306
1307
1308ERRIN: ;DISK ERRORS RETURNED FROM THE IBM ROM
1309 DB 80H ;NO RESPONSE
1310 DB 40H ;Seek failure
1311 DB 10H ;BAD CRC
1312 DB 8 ;DMA OVERRUN
1313 DB 4 ;SECTOR NOT FOUND
1314 DB 3 ;WRITE ATTEMPT TO WRITE-PROTECT DISK
1315LSTERR DB 0 ;ALL OTHER ERRORS
1316
1317
1318ERROUT: ;RETURNED ERROR CODES CORRESPONDING TO ABOVE
1319 DB 2 ;NO RESPONSE
1320 DB 6 ;SEEK FAILURE
1321 DB 4 ;BAD CRC
1322 DB 4 ;DMA OVERRUN
1323 DB 8 ;SECTOR NOT FOUND
1324 DB 0 ;WRITE ATTEMPT ON WRITE-PROTECT DISK
1325 DB 12 ;GENERAL ERROR
1326
1327NUMERR= ERROUT-ERRIN
1328;---------------------------------------------------------------------
1329SPSAV DW 0 ;SAVE THE STACK POINTER
1330;
1331
1332GETBP: PUSH AX
1333 PUSH CX
1334 PUSH DX
1335 PUSH BX
1336 MOV CL,AH ;SAVE MEDIA
1337 AND CL,0F8H ;NORMALIZE
1338 CMP CL,0F8H ;COMPARE WITH GOOD MEDIA BYTE
1339 JZ GOODID
1340 MOV AH,0FEH ;DEFAULT TO 8-SECTOR, SINGLE-SIDED
1341GOODID: MOV DI,OFFSET CS:HDRIVE
1342 CMP AL,[HARDNUM]
1343 JZ GETRET
1344 JB GETBP1
1345 MOV DI,OFFSET CS:DRIVEX
1346 JMP SHORT GETRET
1347
1348GETBP1: MOV AL,1 ;SET NUMBER OF FAT SECTORS
1349 MOV BX,64*256+8 ;SET DIR ENTRIES AND SECTOR MAX
1350 MOV CX,40*8 ;SET SIZE OF DRIVE
1351 MOV DX,01*256+1 ;SET HEAD LIMIT AND SEC/ALL UNIT
1352 MOV DI,OFFSET CS:FDRIVE
1353 TEST AH,00000010B ;TEST FOR 8 OR 9 SECTOR
1354 JNZ HAS8 ;NZ = HAS 8 SECTORS
1355 INC AL ;INC NUMBER OF FAT SECTORS
1356 INC BL ;INC SECTOR MAX
1357 ADD CX,40 ;INCREASE SIZE
1358HAS8: TEST AH,00000001B ;TEST FOR 1 OR 2 HEADS
1359 JZ HAS1 ;Z = 1 HEAD
1360 ADD CX,CX ;DOUBLE SIZE OF DISK
1361 MOV BH,112 ;INCREASE NUMBER OF DIRECTORY ENTRIES
1362 INC DH ;INC SEC/ALL UNIT
1363 INC DL ;INC HEAD LIMIT
1364HAS1: MOV CS:[DI].2,DH
1365 MOV CS:[DI].6,BH
1366 MOV CS:[DI].8,CX
1367 MOV CS:[DI].10,AH
1368 MOV CS:[DI].11,AL
1369 MOV CS:[DI].13,BL
1370 MOV CS:[DI].15,DL
1371GETRET: POP BX
1372RET88: POP DX
1373 POP CX
1374 POP AX
1375 RET
1376
1377;*********************************************************************
1378; "FDRIVE" IS A FLOPPY DISK, VARIOUS PARAMETERS ARE PATCHED
1379; BY GETBP TO REFLECT THE TYPE OF MEDIA INSERTED
1380FDRIVE:
1381 DW 512 ;Physical sector size in bytes
1382 DB 1 ;Sectors/allocation unit
1383 DW 1 ;Reserved sectors for DOS
1384 DB 2 ;No. allocation tables
1385 DW 64 ;Number directory entries
1386 DW 9*40 ;Number sectors (at 512 bytes ea.)
1387 DB 11111100B ;Media descriptor
1388 DW 2 ;Number of FAT sectors
1389 DW 9 ;Sector limit
1390 DW 1 ;Head limit
1391 DW 0 ;Hidden sector count
1392
1393;------------------------------------------------------------
1394;
1395; DISK I/O HANDLER
1396;
1397; AL = DRIVE NUMBER (0-3)
1398; AH = MEDIA DESCRIPTOR
1399; CX = SECTOR COUNT
1400; DX = FIRST SECTOR
1401; ES:DI = TRANSFER ADDRESS
1402; [RFLAG]=OPERATION (2=READ, 3=WRITE)
1403; [VERIFY]=1 FOR VERIFY AFTER WRITE
1404;
1405; IF SUCCESSFUL CARRY FLAG = 0
1406; ELSE CF=1 AND AL CONTAINS ERROR CODE
1407;
1408DISKRD:
1409 debug 1,4,<DISKRD: $x $x $x $x:$x\n>,<ax,cx,dx,es,di>
1410 MOV [RFLAG],2
1411DISKIO:
1412 CLC
1413 JCXZ IORET
1414 MOV [TIM_DRV],AL ;SAVE DRIVE LETTER
1415
1416 MOV [SPSAV],SP ;SAVE SP
1417 XCHG BX,DI ;ES:BX = TRANSFER ADDRESS
1418 CALL GETBP ;CS:DI = PTR TO B.P.B
1419 MOV SI,DX
1420 ADD SI,CX
1421 ADD DX,CS:[DI].HIDSEC ;ADD IN THE HIDDEN SECTORS
1422 CMP SI,CS:[DI].DRVLIM ;COMPARE AGAINST DRIVE MAX
1423 JBE INRANGE
1424 MOV AL,8
1425STCRET: STC
1426IORET: RET
1427
1428INRANGE:CMP AL,[HARDNUM]
1429 JB NOTHARD
1430 MOV AL,CS:[HARDDRV] ;SET DRIVE NUMBER OF HARDFILE
1431 JZ RDWR
1432 INC AL
1433 JMP SHORT RDWR
1434
1435NOTHARD:CMP [SINGLE],1 ;SINGLE FLOPPY INSTALLED?
1436 JNZ RDWR
1437 CALL SWPDSK ;ASK USER FOR CORRECT DISK
1438RDWR:
1439 MOV [DRIVE],AL
1440 MOV [SECCNT],CX ;SAVE SECTOR COUNT
1441 XCHG AX,DX ;SETUP LOGICAL SECTOR FOR DIVIDE
1442 XOR DX,DX
1443 DIV WORD PTR CS:[DI].SECLIM ;DIVIDE BY SEC PER TRACK
1444 INC DL
1445 MOV [CURSEC],DL ;SAVE CURRENT SECTOR
1446 MOV CX,CS:[DI].HDLIM ;GET NUMBER OF HEADS
1447 XOR DX,DX ;DIVIDE TRACKS BY HEADS PER CYLINDER
1448 DIV CX
1449 MOV [CURHD],DL ;SAVE CURRENT HEAD
1450 MOV [CURTRK],AX ;SAVE CURRENT TRACK
1451
1452 debug 1,4,< Drv $b Hd $b Trk $x Sec $b\n>,<<word ptr DRIVE>,<word ptr CURHD>,CURTRK,<word ptr CURSEC>>
1453 MOV AX,[SECCNT]
1454 MOV SI,ES ;Check for 64k boundary error
1455 SHL SI,1
1456 SHL SI,1
1457 SHL SI,1
1458 SHL SI,1 ;Segment converted to absolute address
1459 ADD SI,BX ;Combine with offset
1460 ADD SI,511 ;Add sector size and see if overflow
1461 JC BUFIO ;Must handle special if so
1462
1463 XCHG BX,SI
1464 SHR BH,1
1465 MOV AH,128 ;Max. sectors in 64K
1466 SUB AH,BH ;Number of sectors left in this 64K
1467 XCHG BX,SI
1468
1469 CMP AH,AL ;Does it exceed total request?
1470 JBE FIRBLK
1471 MOV AH,AL ;If so, limit transfer to the request
1472FIRBLK:
1473;At this point, AL=total number of sectors to be read, AH=number
1474; of sectors that can be read before 64K boundary error. AH<=AL.
1475; ES:BX points to load area, DS:DI points to B.P.B
1476
1477 PUSH AX
1478 MOV AL,AH ;No. of sectors to read at once (<>0)
1479 CALL BLOCK ;Transfer portion before boundary
1480 POP AX
1481 SUB AL,AH
1482 JZ DONE
1483BUFIO:
1484 PUSH AX
1485 PUSH ES
1486 PUSH BX ;SAVE CURRENT TRANSFER ADDRESS
1487 CALL SWAP ;SWAP BUFFER WITH BIOS CODE
1488
1489 ADD BH,2 ;POINT TO TEMP BUFFER
1490 CALL DISK1 ;Perform disk operation
1491
1492 POP BX ;RECALL TRANSFER ADDRESS
1493 POP ES
1494 POP AX
1495 CALL SWAP ;SWAP BACK
1496
1497 DEC AL ;Dec sectors to read by 1
1498 ADD BH,2 ;Add 200H to transfer address
1499 CALL BLOCK ;Read the remaining sectors
1500DONE:
1501 debug 1,4,< DISKIO DONE\n>
1502 CLC ;No error
1503 RET ;From subroutine DISKIO
1504
1505; Swap 512 bytes of BIOS with transfer address
1506
1507SWAP: PUSH DI
1508 PUSH BX
1509 PUSH AX
1510 MOV DI,BX ;ES:DI POINTS TO USER BUFFER
1511 ADD BH,2
1512 MOV SI,BX ;ES:SI POINTS TO TEMP BUFFER
1513 CLD
1514 debug 1,4,< SWAP $x:$x <==> $x:$x\n>,<es,di,es,si>
1515 MOV CX,256 ;256 WORDS TO SWAP
1516SWAP1: MOV BX,WORD PTR ES:[DI] ;GET USER WORD
1517 MOV AX,WORD PTR ES:[SI] ;GET SCRATCH WORD
1518 MOV WORD PTR ES:[SI],BX ;PUT SCRATCH WORD
1519 STOSW ;PUT BIOS WORD
1520 INC SI
1521 INC SI
1522 LOOP SWAP1
1523 XOR [SWPFLG],1 ;TOGGLE SWAPPED FLAG
1524 POP AX
1525 POP BX
1526 POP DI
1527RETZ: RET
1528
1529;Read the number of sectors specified in AL, handling track boundaries
1530
1531BLOCK: OR AL,AL ;See if any sectors to read
1532 JZ RETZ
1533
1534 MOV AH,CS:[DI].SECLIM ;Sectors per track
1535 INC AH
1536 SUB AH,[CURSEC] ;Number of sectors left on this track
1537 CMP AH,AL ;Compare with no. of sectors needed
1538 JBE DOIO
1539 MOV AH,AL ;Limit to only those requested
1540DOIO:
1541 PUSH AX
1542 MOV AL,AH ;Put count where ROM needs it
1543 CALL DISK ;Call ROM and trap errors
1544 POP AX
1545 SUB AL,AH ;Reduce request by amount just done
1546 SHL AH,1 ;AH * 2^8 = no. of bytes
1547 ADD BH,AH ;Bump address pointer
1548 JMP BLOCK
1549
1550;Perform disk I/O with retries
1551; AL = number of sectors (1-8, all on one track)
1552; ES:BX = Transfer address (must not cross a 64K physical boundary)
1553; [RFLAG] = 2 if read, 3 if write
1554; [VERIFY] = 0 for normal, 1 for verify after write
1555
1556DISK1: MOV AL,1 ;Only one sector for buffered I/O
1557
1558DISK: MOV SI,MAXERR
1559 MOV AH,RFLAG ;Get read/write indicator
1560
1561RETRY: PUSH AX
1562
1563CALLROM:MOV DX,[CURTRK] ;Load current cylinder
1564 MOV CL,6 ;move high bits of cyl to sec
1565 SHL DH,CL
1566 OR DH,[CURSEC]
1567 MOV CX,DX
1568 XCHG CH,CL ;CL = sector, CH = cylinder
1569 MOV DX,WORD PTR [DRIVE] ;Load physical drive number
1570 ;and current head number
1571;; debug 1,4,< CALLROM $x $x $x $x $x\n>,<ax,bx,cx,dx,es>
1572 INT 13H ;Request disk read/write
1573 JC DSKERR
1574 POP AX ;Restore sector count
1575 PUSH AX
1576 CMP WRTVERIFY,103H ;Check for write and verify
1577 JNZ NOVERIFY
1578 MOV AH,4 ;Request verify
1579 INT 13H
1580 JC DSKERR
1581NOVERIFY:
1582;; debug 1,4,< back from ROM\n>,<>
1583 POP AX
1584 AND CL,03FH ;Eliminate cylinder bits from sector
1585 XOR AH,AH
1586 SUB [SECCNT],AX ;Reduce count of sectors to go
1587 ADD CL,AL ;Next sector
1588 MOV [CURSEC],CL
1589 CMP CL,CS:[DI].SECLIM ; Reached limit?
1590 JBE RET1
1591
1592 MOV [CURSEC],1 ;Start with first sector of next track
1593 MOV DH,[CURHD]
1594 INC DH
1595 CMP DH,CS:[DI].HDLIM
1596 JB NOXOR
1597 XOR DH,DH
1598 INC [CURTRK] ;NEXT TRACK
1599NOXOR: MOV [CURHD],DH
1600
1601RET1: RET
1602
1603DSKERR:
1604 debug 1,4,< DSKERR $x >,<ax>
1605 PUSH AX ;Save error code
1606 MOV AH,0 ;Ask for disk reset
1607 INT 13H
1608 POP AX ;Restore error code
1609 DEC SI ;decrement retry count
1610 JZ HARDERR
1611 CMP AH,80H ;Timeout?
1612 JZ HARDERR ;***
1613DSKERR1:POP AX ;Restore sector count
1614 JMP RETRY
1615
1616HARDERR:
1617 CMP [SWPFLG],0 ;If BIOS swapped out
1618 JZ HARD1
1619 POP BX ;Get disk1 return address
1620 POP BX ;Get low part of transfer address
1621 POP ES ;Get high part of transfer address
1622 CALL SWAP ;swap it back in
1623HARD1: PUSH CS
1624 POP ES ;Make ES the local segment
1625 MOV AL,AH ;Put error code in AL
1626 MOV [LSTERR],AL ;Terminate list with error code
1627 MOV CX,NUMERR ;Number of possible error conditions
1628 MOV DI,OFFSET CS:ERRIN ;Point to error conditions
1629 REPNE SCASB
1630 MOV AL,es:NUMERR-1[DI] ;Get translation
1631 MOV CX,SECCNT ;Get count of sectors to go
1632 MOV SP,[SPSAV] ;Recover entry stack pointer
1633 STC ;Flag error condition
1634 RET ;and return
1635
1636INITAB DW FDRIVE
1637 DW FDRIVE
1638 DW FDRIVE
1639 DW FDRIVE
1640INITABH DW HDRIVE
1641 DW DRIVEX
1642
1643RomData SEGMENT AT 040H
1644 ORG 03EH
1645Seek_Status DB 1 DUP(?)
1646RomData ENDS
1647
1648
1649;-------------------------------------------------
1650;
1651; ASK TO SWAP THE DISK IN DRIVE A:
1652;
1653SWPDSK: PUSH DS
1654 XOR SI,SI ;Select segment 0
1655 MOV DS,SI
1656 MOV AH,AL ;Make copy of drive number
1657 XCHG AH,DS:LSTDRV ;Xchange with last drive used
1658 CMP AL,AH ;See if same as last drive
1659 JZ RDWR0
1660;Using a different drive in a one drive system so request the user change disks
1661 ADD AL,"A" ;Add "A" to convert to drive letter
1662 MOV CS:DRVLET,AL
1663 push cs
1664 pop ds
1665 MOV SI,OFFSET CS:SNGMSG
1666 PUSH BX
1667 CALL WRMSG ;Print disk change message
1668 XOR AH,AH
1669 INT 16H ;Wait for a keyboard character
1670 POP BX
1671RDWR0:
1672 POP DS
1673 XOR AL,AL ;Always use drive 0
1674 RET
1675
1676
1677SNGMSG DB CR,LF,"Insert diskette for drive "
1678DRVLET DB "A: and strike",CR,LF,"any key when ready",CR,LF,LF,0
1679HNUM DB 0 ;NUMBER OF HARDFILES
1680
1681
1682;** End of Permanently Resident BIOS
1683
1684
1685HARDDRV DB 80H ;Physical drive number of first hardfile
1686;**********************************************************************
1687; "HDRIVE" IS A HARD DISK WITH 512 BYTE SECTORS
1688;*********************************************************************
1689HDRIVE:
1690 DW 512
1691 DB 1 ;Sectors/allocation unit
1692 DW 1 ;Reserved sectors for DOS
1693 DB 2 ;No. of allocation tables
1694 DW 16 ;Number of directory entries
1695 DW 0000 ;Number of sectors (at 512 bytes each)
1696 DB 11111000B ;Media descriptor
1697 DW 1 ;Number of FAT sectors
1698 DW 00 ;Sector limit
1699 DW 00 ;Head limit
1700 DW 00 ;Hidden sector count
1701;**********************************************************************
1702; "DRIVEX " IS AN EXTRA TYPE OF DRIVE USUALLY RESERVED FOR AN
1703; ADDITIONAL HARD FILE
1704;*********************************************************************
1705DRIVEX:
1706 DW 512
1707 DB 00 ;Sectors/allocation unit
1708 DW 1 ;Reserved sectors for DOS
1709 DB 2 ;No. of allocation tables
1710 DW 0000 ;Number of directory entries
1711 DW 0000 ;Number of sectors (at 512 bytes each)
1712 DB 11111000B ;Media descriptor
1713 DW 0000 ;Number of FAT sectors
1714 DW 00 ;Sector limit
1715 DW 00 ;Head limit
1716 DW 00 ;Hidden sector count
1717
1718SUBTTL Bios initialization
1719 ;*********************************************************
1720; SYSTEM INITIALIZATION
1721;
1722; THE ENTRY CONDITIONS ARE ESTABLISHED BY THE BOOTSTRAP
1723; LOADER AND ARE CONSIDERED UNKNOWN. THE FOLLOWING JOBS
1724; WILL BE PERFORMED BY THIS MODULE:
1725;
1726; 1. ALL DEVICE INITIALIZATION IS PERFORMED
1727; 2. A LOCAL STACK IS SET UP AND DS:SI ARE SET
1728; TO POINT TO AN INITIALIZATION TABLE. THEN
1729; AN INTER-SEGMENT CALL IS MADE TO THE FIRST
1730; BYTE OF THE DOS
1731; 3. ONCE THE DOS RETURNS FROM THIS CALL THE DS
1732; REGISTER HAS BEEN SET UP TO POINT TO THE START
1733; OF FREE MEMORY. THE INITIALIZATION WILL THEN
1734; LOAD THE COMMAND PROGRAM INTO THIS AREA
1735; BEGINNING AT 100 HEX AND TRANSFER CONTROL TO
1736; THIS PROGRAM.
1737;
1738;********************************************************
1739
1740DRVFAT DW 0000 ;DRIVE AND FAT ID OF DOS
1741BIOS$ DW 0000 ;FIRST SECTOR OF DATA
1742DOSCNT DW 0000 ;HOW MANY SECTORS TO READ
1743
1744BootBufr EQU 17C0H ; High memory scratch area
1745
1746 ASSUME DS:NOTHING,ES:NOTHING
1747
1748INIT: mov dx,1000h
1749 MOV SS,DX
1750 MOV SP,7C00h ;LOCAL STACK 1000:7C00
1751 STI
1752 PUSH CX ;Save number of floppies
1753 MOV [BIOS$],BX
1754 PUSH AX ;Save Drive info
1755 MOV AL,EOI
1756 OUT AKPORT,AL ;TURN ON THE TIMER
1757
1758 MOV SI,OFFSET LPT3DEV
1759 CALL PRINT_INIT ;INIT LPT3
1760 MOV SI,OFFSET LPT2DEV
1761 CALL PRINT_INIT ;INIT LPT2
1762 MOV SI,OFFSET LPT1DEV
1763 CALL PRINT_INIT ;INIT LPT1
1764
1765 MOV SI,OFFSET COM2DEV
1766 CALL AUX_INIT ;INIT COM2
1767 MOV SI,OFFSET COM1DEV
1768 CALL AUX_INIT ;INIT COM1
1769;* Can't do any DEBUG prints till now
1770 debug 1,1,<AUX and PRN devices initialized\n>,<>
1771 XOR DX,DX
1772 MOV DS,DX ;TO INITIALIZE PRINT SCREEN VECTOR
1773 MOV ES,DX
1774
1775 MOV AX,CS ;FETCH SEGMENT
1776
1777IF CONSFLAG
1778 MOV WORD PTR DS:BRKADR,OFFSET BREAK
1779 MOV DS:BRKADR+2,AX ;VECTOR FOR BREAK
1780 MOV WORD PTR DS:(CHROUT*4),OFFSET OUTCHR
1781 MOV DS:(CHROUT*4+2),AX
1782ENDIF
1783 MOV WORD PTR DS:DSKADR,SEC9 ;DISK PARAMETERS
1784 MOV DS:DSKADR+2,ES
1785
1786 MOV DI,4
1787 MOV BX,OFFSET INTRET ; Rest just return
1788 XCHG AX,BX
1789 STOSW ;Location 4
1790 XCHG AX,BX
1791 STOSW ;INT 1 ;Location 6
1792 ADD DI,4
1793 XCHG AX,BX
1794 STOSW ;Location 12
1795 XCHG AX,BX
1796 STOSW ;INT 3 ;Location 14
1797 XCHG AX,BX
1798 STOSW ;Location 16
1799 XCHG AX,BX
1800 STOSW ;INT 4 ;Location 18
1801; Set up some vectors for scheduler and change rom interrupts
1802;
1803 CLI ; Disable, changing int vectors
1804 ADD DI,3*4 ; Move up to INT 8
1805 MOV CX,OFFSET TimerInterrupt
1806 XCHG AX,CX
1807 STOSW
1808 XCHG AX,CX
1809 STOSW ; Set new INT 8: Timer
1810IF CONSFLAG
1811 MOV CX,DS:[DI] ; Save old addr to hook to
1812 MOV WORD PTR OldKeyInterrupt,CX
1813 MOV CX,DS:2[DI]
1814 MOV WORD PTR (OldKeyInterrupt+2),CX
1815 MOV CX,OFFSET KeyboardInterrupt
1816 XCHG AX,CX
1817 STOSW
1818 XCHG AX,CX
1819 STOSW ; Set new keyboard interrupt
1820ELSE
1821 ADD DI,4
1822ENDIF
1823 XCHG AX,BX
1824 STOSW
1825 XCHG AX,BX ; INT 0A unused
1826 STOSW
1827 XCHG AX,BX
1828 STOSW
1829 XCHG AX,BX ; INT 0B unused
1830 STOSW
1831 add di,4*6 ; skip 0C - 11
1832 MOV CX,DS:[DI] ; Save INT 12 addr to hook to
1833 MOV WORD PTR memsizint,CX
1834 MOV CX,DS:2[DI]
1835 MOV WORD PTR (memsizint+2),CX
1836 mov cx,offset memsizhandler
1837 xchg ax,cx
1838 stosw
1839 xchg ax,cx
1840 stosw
1841 add di,4*2 ; skip 13 - 14
1842 STI
1843; End of new 3.0 vectors
1844 XCHG AX,BX
1845 STOSW ;INT 15 ;Location 60
1846 XCHG AX,BX
1847 STOSW ;Location 62
1848IF CONSFLAG
1849 MOV CX,DS:[DI] ; Save INT 16 addr to hook to
1850 MOV WORD PTR OldKbdHandler,CX
1851 MOV CX,DS:2[DI]
1852 MOV WORD PTR (OldKbdHandler+2),CX
1853 MOV CX,OFFSET KeyboardHandler
1854 XCHG AX,CX
1855 STOSW
1856 XCHG AX,CX ; Set new keyboard Handler
1857 STOSW
1858; Set new get/set time vector, time base changed
1859 ADD DI,4*3 ; skip 17 - 19
1860ELSE
1861 ADD DI,4*4 ; skip 16 - 19
1862ENDIF ;CONSFLAG
1863 MOV CX,OFFSET TimeOfDay
1864 XCHG AX,CX
1865 STOSW ; setup 1A to TimeofDay
1866 XCHG AX,CX
1867 STOSW
1868 ADD DI,4*23 ; skip 1B - 31
1869 XCHG AX,BX
1870 STOSW ; no-op INT 32 until Sched:SchedInit
1871 XCHG AX,BX
1872 STOSW
1873 debug 1,1,<Interrupt vectors initialized\n>,<>
1874
1875 MOV DS:WORD PTR 500H,DX ;SET PRINT SCREEN & BREAK =0
1876 MOV DS:WORD PTR LSTDRV,DX ;clean out last drive spec
1877
1878 MOV DI,SEC9 ;location of drive table
1879 MOV AX,02DFH ;Stuff the disk speedup/9 sector
1880 STOSW ;code
1881 MOV AX,0225H
1882 STOSW
1883 MOV AX,2A09H
1884 STOSW
1885 MOV AX,50FFH
1886 STOSW
1887 MOV AX,00F6H
1888 STOSW
1889 MOV AL,2
1890 STOSB
1891
1892 pushf ;simulate int 12h
1893 call memsizint ;Get memory size--1K blocks in AX
1894 MOV CL,6
1895 SHL AX,CL ;Convert to 16-byte blocks(segment no.)
1896 POP CX ;Recall drive info
1897 MOV [DRVFAT],CX ;SAVE DRIVE TO LOAD DOS
1898
1899 MOV DX,SEG SYSINIT
1900 MOV DS,DX
1901
1902 ASSUME DS:SEG SYSINIT
1903
1904 MOV MEMORY_SIZE,AX
1905 INC CL
1906 MOV DEFAULT_DRIVE,CL ;SAVE DEFAULT DRIVE SPEC
1907
1908 add dx,SYSIZE
1909 MOV CURRENT_DOS_LOCATION,dx ; load address of DOS
1910
1911 MOV FINAL_DOS_LOCATION,SEG BiosInit
1912 debug 1,2,<DOS will load at $x, will move to $x\n>,<dx,FINAL_DOS_LOCATION>
1913 MOV WORD PTR DEVICE_LIST,OFFSET CONDEV ;DS:SI = ptr to device list
1914 MOV AX,CS
1915 MOV WORD PTR DEVICE_LIST+2,AX
1916;**************************************************************
1917; WILL INITIALIZE THE NUMBER OF DRIVES
1918; AFTER THE EQUIPMENT CALL (INT 11H) BITS 6&7 WILL TELL
1919; THE INDICATIONS ARE AS FOLLOWS:
1920;
1921; BITS 7 6 DRIVES
1922; 0 0 1
1923; 0 1 2
1924; 1 0 3
1925; 1 1 4
1926;**************************************************************
1927 PUSH CS
1928 PUSH CS
1929 POP DS
1930 POP ES
1931
1932 ASSUME DS:BiosSeg,ES:BiosSeg
1933
1934 INT 11H ;GET EQUIPMENT STATUS
1935 AND AL,11000000B ;MASK DRIVE BITS
1936 JNZ NOTSNGL ;Zero means single drive system
1937 INC [SINGLE] ;REMEMBER THIS
1938NOTSNGL:
1939 POP AX ;BOOT specifies number of floppies
1940 MOV [HARDNUM],AL ;Remember which drive is hard disk
1941 MOV [DRVMAX],AL ;And set initial number of drives
1942 MOV AH,8
1943 MOV DL,80H
1944 INT 13H ;Request number of hardfiles attached
1945 JC ENDDRV ;Carry indicates old rom, so no hardfile
1946 MOV [HNUM],DL
1947ENDDRV:
1948 MOV DL,80H
1949 MOV DI,OFFSET CS:HDRIVE
1950 CMP [HNUM],0
1951 JLE ITSOK1
1952 CALL SETHRD ;SET UP FIRST HARDFILE
1953
1954 MOV DL,81H ;SET UP FOR NEXT CALL
1955 MOV DI,OFFSET CS:DRIVEX
1956 JC NOTOK
1957 CMP [HNUM],2
1958 JZ SETIT
1959 JMP SHORT ITSOK
1960
1961NOTOK: MOV [HARDDRV],DL
1962 MOV DI,OFFSET CS:HDRIVE
1963 DEC [HNUM]
1964 CMP [HNUM],0
1965 JZ ITSOK1
1966SETIT: CALL SETHRD ;SET UP SECOND HARDFILE
1967 JNC ITSOK
1968 DEC [HNUM]
1969
1970; End of drive initialization
1971
1972ITSOK: MOV AL,[HNUM]
1973 OR AL,AL
1974 JZ ITSOK1
1975 ADD AL,[HARDNUM]
1976 MOV [DRVMAX],AL
1977 MOV AL,[HNUM]
1978 JMP SHORT ITSOK2 ;GO SET DESTINATION SEGMENT
1979
1980ITSOK1: CMP BYTE PTR [SINGLE],1
1981 JMP SHORT GOINIT
1982
1983 ASSUME DS:BiosSeg
1984
1985ITSOK2:
1986 DEC AL
1987
1988GOINIT:
1989 debug 1,1,<hardnum/hnum $x drvfat $x\n>,<<word ptr hnum>,drvfat>
1990 PUSH CS
1991 POP DS
1992
1993 ASSUME DS:BiosSeg,ES:NOTHING
1994
1995 CALL GETFAT ;READ IN THE FAT SECTOR
1996 XOR DI,DI
1997 MOV AL,ES:[DI] ;GET FAT ID BYTE
1998 MOV BYTE PTR DRVFAT+1,AL ;SAVE FAT BYTE
1999 debug 1,2,< FAT ID: $b ds:$x\n>,<ax,ds>
2000 MOV AX,[DRVFAT]
2001 CALL GETBP ;GET DISK POINTER
2002 MOV CL,[DI+2] ;GET SECTORS/CLUSTER
2003 MOV AX,[DI].HIDSEC ;GET NUMBER OF HIDDEN SECTORS
2004 SUB [BIOS$],AX ;SUBTRACT HIDDEN SECTOR OFFSET
2005 XOR CH,CH ;CX = SECTORS/CLUSTER
2006 PUSH DS
2007 XOR DI,DI
2008 MOV DS,DI
2009;
2010; THE BOOT PROGRAM HAS LEFT THE DIRECTORY AT 0:500
2011;
2012 MOV BX,DS:WORD PTR 53AH ;GET FIRST CLUSTER OF DOS
2013 POP DS ;BX = FIRST CLUSTER OF DOS
2014LOADIT: MOV AX,SEG SYSINIT
2015 add ax,SYSIZE
2016 MOV ES,AX ;ES:DI POINTS TO LOAD LOCATION
2017 CALL GETCLUS ;READ IN A CLUSTER
2018 CMP BX,0FFFH
2019 JNZ LOADIT ;END OF FILE?
2020
2021 EXTRN Disk_Init:NEAR
2022 call Disk_Init ; do some device driver initialization
2023 debug 1,2,<System loaded, going to sysinit\n>,<>
2024 JMP SYSINIT
2025
2026SUBTTL Routines for reading in MSDOS
2027
2028;
2029; READ A FAT SECTOR INTO 17C0:0
2030;
2031GETFAT: debug 1,2,<GETFAT.>,<>
2032 XOR DI,DI
2033 MOV CX,1
2034 MOV DX,CX
2035 MOV AX,BootBufr
2036 MOV ES,AX
2037 MOV AL,BYTE PTR DRVFAT
2038 MOV AH,0FCH
2039 JMP DISKRD
2040;
2041; READ A BOOT RECORD INTO 17C0:0
2042;
2043GETBOOT:debug 1,2,<GETBOOT.>,<>
2044 MOV CX,1
2045 MOV AX,0201H
2046 MOV BX,BootBufr
2047 MOV ES,BX
2048 XOR BX,BX
2049 MOV DH,BH
2050 INT 13H
2051 JC SETRET
2052 CMP WORD PTR ES:[1FEH],0AA55H
2053 JNZ SETRET
2054 RET
2055;
2056; SETUP VARIABLE SIZED HARDFILE
2057; ON ENTRY DL=DRIVE NUMBER (80 OR 81)
2058; DI=PTR TO B.P.B
2059;
2060SETHRD: PUSH DX
2061 MOV AH,8 ;GET DRIVE PARAMETERS
2062 INT 13H
2063 INC DH
2064 MOV [DI].HDLIM,DH
2065 POP DX
2066 JC SETRET
2067 AND CL,3FH
2068 MOV [DI].SECLIM,CL
2069 CALL GETBOOT ;GET THE BOOT RECORD
2070 JC SETRET
2071 MOV BX,1C2H
2072SET1: CMP BYTE PTR ES:[BX],1
2073 JZ SET2
2074 ADD BX,16
2075 CMP BX,202H
2076 JNZ SET1
2077SETRET: STC ;NOT FOUND SO USE DEFAULTS
2078 RET
2079
2080SET2: MOV AX,ES:[BX+4]
2081 MOV DS:[DI].HIDSEC,AX ;SET HIDDEN SECTOR COUNT
2082 MOV AX,ES:[BX+8]
2083 CMP AX,64 ;HAS TO BE AT LEAST 32K
2084 JB SETRET
2085 MOV DS:[DI].8,AX ;SAVE LOGICAL SECTOR COUNT
2086 MOV CX,0100H ;SET CLUS SIZE AND SHIFT COUNT
2087 MOV DX,64 ;SET NUMBER OF DIR ENTRIES
2088 CMP AX,512
2089 JBE SET3
2090
2091 ADD CH,CH
2092 INC CL
2093 MOV DX,112
2094 CMP AX,2048
2095 JBE SET3
2096
2097 ADD CH,CH
2098 INC CL
2099 MOV DX,256
2100 CMP AX,8192
2101 JBE SET3
2102
2103 ADD CH,CH
2104 INC CL
2105 ADD DX,DX
2106 CMP AX,32680 ;NOT 32768! MAX NUMBER OF CLUSTERS=4085
2107 JBE SET3
2108
2109 ADD CH,CH
2110 INC CL
2111 ADD DX,DX
2112SET3:
2113;
2114; DX=NUMBER OF DIR ENTRIES, CH=NUMBER OF SECTORS PER CLUSTER
2115; CL=LOG BASE 2 OF CH
2116;
2117; NOW CALCULATE SIZE OF FAT TABLE
2118;
2119 MOV [DI].6,DX ;SAVE NUMBER OF DIR ENTRIES
2120 MOV [DI].2,CH ;SAVE SECTORS PER CLUSTER
2121 XOR BX,BX
2122 MOV BL,CH
2123 DEC BX
2124 ADD BX,AX
2125 SHR BX,CL ;DIVIDE BY SECTORS/CLUSTER
2126 INC BX
2127 AND BL,11111110B ;MAKE SURE COUNT IS EVEN
2128 MOV SI,BX
2129 SHR BX,1
2130 ADD BX,SI ;MULTIPY BY 1.5
2131 ADD BX,511
2132 SHR BH,1
2133 MOV [DI].11,BH ;SAVE NUMBER OF FAT SECTORS
2134 CLC
2135 RET
2136;
2137; READ CLUSTER SPECIFIED IN BX
2138; CX = SECTORS PER CLUSTER
2139; DI = LOAD LOCATION
2140;
2141GETCLUS:debug 1,2,<GETCLUS bx $x cx $x es:di $x:$x >,<bx,cx,es,di>
2142 PUSH CX
2143 PUSH DI
2144 MOV [DOSCNT],CX ;SAVE NUMBER OF SECTORS TO READ
2145 MOV AX,BX
2146 DEC AX
2147 DEC AX
2148 MUL CX ;CONVERT TO LOGICAL SECTOR
2149 ADD AX,[BIOS$] ;ADD IN FIRST DATA SECTOR
2150 MOV DX,AX ;DX = FIRST SECTOR TO READ
2151
2152GETCL1: CALL UNPACK ;SI = BX, BX = NEXT ALLOCATION UNIT
2153 SUB SI,BX
2154 CMP SI,-1 ;one apart?
2155 JNZ GETCL2
2156 ADD [DOSCNT],CX
2157 JMP GETCL1
2158
2159GETCL2: PUSH BX
2160 MOV AX,[DRVFAT] ;GET DRIVE AND FAT SPEC
2161 MOV CX,[DOSCNT]
2162 CALL DISKRD ;READ THE CLUSTERS
2163 POP BX
2164 POP DI
2165 MOV AX,[DOSCNT] ;GET NUMBER OF SECTORS READ
2166 XCHG AH,AL ;MULTIPLY BY 256
2167 SHL AX,1 ;TIMES 2 EQUAL 512
2168 ADD DI,AX ;UPDATE LOAD LOCATION
2169 POP CX ;RESTORE SECTORS/CLUSTER
2170 RET
2171;
2172; GET THE FAT ENTRY AT BX, WHEN FINISHED SI=ENTRY BX
2173;
2174UNPACK: PUSH DS
2175 PUSH BX
2176 MOV SI,BootBufr
2177 MOV DS,SI
2178 MOV SI,BX
2179 SHR SI,1
2180 MOV BX,[SI+BX]
2181 JNC HAVCLUS
2182 SHR BX,1
2183 SHR BX,1
2184 SHR BX,1
2185 SHR BX,1
2186HAVCLUS:AND BX,0FFFH
2187 POP SI
2188 POP DS
2189 RET
2190;
2191; SI POINTS TO DEVICE HEADER
2192;
2193PRINT_INIT:
2194 MOV BH,1
2195 MOV DL,17H
2196 JMP SHORT DEV_INIT
2197AUX_INIT:
2198 MOV BX,RSINIT
2199 MOV DL,14H
2200DEV_INIT:
2201 MOV CS:[INTNUM],DL
2202 MOV AL,CS:[SI+13] ;GET DEVICE NUMBER FROM THE NAME
2203 SUB AL,"1"
2204 CBW
2205 MOV DX,AX
2206 MOV AX,BX ;SET THE CALL
2207 DB 0CDH ;INT 17H
2208INTNUM DB 17H
2209 RET
2210
2211END$:
2212
2213BiosInit ENDS
2214 END