summaryrefslogtreecommitdiff
path: root/v4.0-ozzie
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0-ozzie')
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - 286 Compatability.pdfbin0 -> 14973858 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Command Guide.pdfbin0 -> 967862 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Device Drivers.pdfbin0 -> 18568764 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Dynamic Linking.pdfbin0 -> 17943810 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Intro.pdfbin0 -> 9589043 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Memory Management.pdfbin0 -> 20166638 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Overview.pdfbin0 -> 19636041 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Release Notes.pdfbin0 -> 573075 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Session Manager.pdfbin0 -> 1323664 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - System Calls.pdfbin0 -> 15351778 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Welcome Beta Site Letter.pdfbin0 -> 386096 bytes
-rw-r--r--v4.0-ozzie/Multitasking DOS BETA - Welcome OEMs Letter.pdfbin0 -> 433751 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/AUTOEXEC.BAT5
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/ARENA.EXEbin0 -> 768 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/BBSET.EXEbin0 -> 19107 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/CHKDSK.EXEbin0 -> 9084 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/COUNTDOW.EXEbin0 -> 12963 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/DEMO1.BAT3
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/DEMO2.BAT4
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/DEMO3.BAT7
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/DETACH.EXEbin0 -> 15411 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/HE_DAEM.EXEbin0 -> 9955 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/KILL.EXEbin0 -> 13683 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/POUND.EXEbin0 -> 15363 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/PRIME.BASbin0 -> 90 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/SLEEP.EXEbin0 -> 13875 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/SM.EXEbin0 -> 28675 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/BIN/TEXT.EXEbin0 -> 6355 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/COMMAND.COMbin0 -> 14934 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/COMMANDS.DOC199
-rw-r--r--v4.0-ozzie/bin/DISK1/CONFIG.SYS3
-rw-r--r--v4.0-ozzie/bin/DISK1/DOS33/FDISK.COMbin0 -> 48216 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/DOS33/FORMAT.COMbin0 -> 11616 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/DOS33/SYS.COMbin0 -> 4766 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/IBMBIO.COMbin0 -> 12363 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/IBMDOS.COMbin0 -> 49324 bytes
-rw-r--r--v4.0-ozzie/bin/DISK1/README67
-rw-r--r--v4.0-ozzie/bin/DISK1/SM.DOC199
-rw-r--r--v4.0-ozzie/bin/DISK1/SM.INI2
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/ANSI.INC573
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/BIOSOBJ.MAK20
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/BOOTPACH.EXEbin0 -> 14099 bytes
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC553
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/DEFDBUG.INC122
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.ASM2214
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.OBJbin0 -> 4761 bytes
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.ASM2551
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.OBJbin0 -> 7477 bytes
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.ASM1424
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.OBJbin0 -> 4586 bytes
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/READ_ME25
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/SYSIMES.OBJbin0 -> 306 bytes
-rw-r--r--v4.0-ozzie/bin/DISK2/BIOS/SYSINI.OBJbin0 -> 3616 bytes
-rw-r--r--v4.0-ozzie/bin/DRDOS1.IMDbin0 -> 361321 bytes
-rw-r--r--v4.0-ozzie/bin/DRDOS1_IMD.imgbin0 -> 368640 bytes
-rw-r--r--v4.0-ozzie/bin/DRDOS2.IMDbin0 -> 281094 bytes
-rw-r--r--v4.0-ozzie/bin/DRDOS2_IMD.imgbin0 -> 368640 bytes
57 files changed, 7971 insertions, 0 deletions
diff --git a/v4.0-ozzie/Multitasking DOS BETA - 286 Compatability.pdf b/v4.0-ozzie/Multitasking DOS BETA - 286 Compatability.pdf
new file mode 100644
index 0000000..e56cb3d
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - 286 Compatability.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Command Guide.pdf b/v4.0-ozzie/Multitasking DOS BETA - Command Guide.pdf
new file mode 100644
index 0000000..6df8d3d
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Command Guide.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Device Drivers.pdf b/v4.0-ozzie/Multitasking DOS BETA - Device Drivers.pdf
new file mode 100644
index 0000000..7054542
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Device Drivers.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Dynamic Linking.pdf b/v4.0-ozzie/Multitasking DOS BETA - Dynamic Linking.pdf
new file mode 100644
index 0000000..d40f2c5
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Dynamic Linking.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Intro.pdf b/v4.0-ozzie/Multitasking DOS BETA - Intro.pdf
new file mode 100644
index 0000000..abc1ee9
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Intro.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Memory Management.pdf b/v4.0-ozzie/Multitasking DOS BETA - Memory Management.pdf
new file mode 100644
index 0000000..c9f9a07
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Memory Management.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Overview.pdf b/v4.0-ozzie/Multitasking DOS BETA - Overview.pdf
new file mode 100644
index 0000000..ce6f077
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Overview.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Release Notes.pdf b/v4.0-ozzie/Multitasking DOS BETA - Release Notes.pdf
new file mode 100644
index 0000000..8a632f3
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Release Notes.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Session Manager.pdf b/v4.0-ozzie/Multitasking DOS BETA - Session Manager.pdf
new file mode 100644
index 0000000..5c02646
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Session Manager.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - System Calls.pdf b/v4.0-ozzie/Multitasking DOS BETA - System Calls.pdf
new file mode 100644
index 0000000..e09f284
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - System Calls.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Welcome Beta Site Letter.pdf b/v4.0-ozzie/Multitasking DOS BETA - Welcome Beta Site Letter.pdf
new file mode 100644
index 0000000..80cbbdb
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Welcome Beta Site Letter.pdf
Binary files differ
diff --git a/v4.0-ozzie/Multitasking DOS BETA - Welcome OEMs Letter.pdf b/v4.0-ozzie/Multitasking DOS BETA - Welcome OEMs Letter.pdf
new file mode 100644
index 0000000..a19def0
--- /dev/null
+++ b/v4.0-ozzie/Multitasking DOS BETA - Welcome OEMs Letter.pdf
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/AUTOEXEC.BAT b/v4.0-ozzie/bin/DISK1/AUTOEXEC.BAT
new file mode 100644
index 0000000..7842e98
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/AUTOEXEC.BAT
@@ -0,0 +1,5 @@
1date
2time
3prompt $p$g
4path a:\bin;a:\
5 \ No newline at end of file
diff --git a/v4.0-ozzie/bin/DISK1/BIN/ARENA.EXE b/v4.0-ozzie/bin/DISK1/BIN/ARENA.EXE
new file mode 100644
index 0000000..0bf52f1
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/ARENA.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/BBSET.EXE b/v4.0-ozzie/bin/DISK1/BIN/BBSET.EXE
new file mode 100644
index 0000000..1414161
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/BBSET.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/CHKDSK.EXE b/v4.0-ozzie/bin/DISK1/BIN/CHKDSK.EXE
new file mode 100644
index 0000000..3a6dded
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/CHKDSK.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/COUNTDOW.EXE b/v4.0-ozzie/bin/DISK1/BIN/COUNTDOW.EXE
new file mode 100644
index 0000000..148ce1c
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/COUNTDOW.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/DEMO1.BAT b/v4.0-ozzie/bin/DISK1/BIN/DEMO1.BAT
new file mode 100644
index 0000000..c4f8563
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/DEMO1.BAT
@@ -0,0 +1,3 @@
1cd bin
2pound 290 a:bbset.exe a:sm.exe
3 \ No newline at end of file
diff --git a/v4.0-ozzie/bin/DISK1/BIN/DEMO2.BAT b/v4.0-ozzie/bin/DISK1/BIN/DEMO2.BAT
new file mode 100644
index 0000000..49fe3d6
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/DEMO2.BAT
@@ -0,0 +1,4 @@
1c:
2cd \bin
3pound 800 bbset.exe sm.exe
4 \ No newline at end of file
diff --git a/v4.0-ozzie/bin/DISK1/BIN/DEMO3.BAT b/v4.0-ozzie/bin/DISK1/BIN/DEMO3.BAT
new file mode 100644
index 0000000..eb99c7b
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/DEMO3.BAT
@@ -0,0 +1,7 @@
1c:
2cd \bin
3cd a:\bin
4detach pound 800 bbset.exe sm.exe
5detach pound 290 a:bbset.exe a:sm.exe
6basica a:prime
7 \ No newline at end of file
diff --git a/v4.0-ozzie/bin/DISK1/BIN/DETACH.EXE b/v4.0-ozzie/bin/DISK1/BIN/DETACH.EXE
new file mode 100644
index 0000000..dc75d46
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/DETACH.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/HE_DAEM.EXE b/v4.0-ozzie/bin/DISK1/BIN/HE_DAEM.EXE
new file mode 100644
index 0000000..3cf823b
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/HE_DAEM.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/KILL.EXE b/v4.0-ozzie/bin/DISK1/BIN/KILL.EXE
new file mode 100644
index 0000000..ef240b6
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/KILL.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/POUND.EXE b/v4.0-ozzie/bin/DISK1/BIN/POUND.EXE
new file mode 100644
index 0000000..1ed27f1
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/POUND.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/PRIME.BAS b/v4.0-ozzie/bin/DISK1/BIN/PRIME.BAS
new file mode 100644
index 0000000..a088c0c
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/PRIME.BAS
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/SLEEP.EXE b/v4.0-ozzie/bin/DISK1/BIN/SLEEP.EXE
new file mode 100644
index 0000000..fdeaa14
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/SLEEP.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/SM.EXE b/v4.0-ozzie/bin/DISK1/BIN/SM.EXE
new file mode 100644
index 0000000..15da78c
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/SM.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/BIN/TEXT.EXE b/v4.0-ozzie/bin/DISK1/BIN/TEXT.EXE
new file mode 100644
index 0000000..edcc27f
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/BIN/TEXT.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/COMMAND.COM b/v4.0-ozzie/bin/DISK1/COMMAND.COM
new file mode 100644
index 0000000..3546cbd
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/COMMAND.COM
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/COMMANDS.DOC b/v4.0-ozzie/bin/DISK1/COMMANDS.DOC
new file mode 100644
index 0000000..0fcfed7
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/COMMANDS.DOC
@@ -0,0 +1,199 @@
1
2
3
4
5
6
7 Multi-Tasking MS-DOS
8 Beta Test Release 1.00
9
10 Command Guide
11
12
13 ARENA.EXE - Prints out arena assignments
14
15 arena
16
17 The system's memory arena is printed out. The
18 number listed under the owner field is the PID of
19 the process which owns the memory.
20
21
22 BBSET.EXE - Set and report on behavior bits
23
24 bbset [-o] [ {+|-}bitname ... ] fname ...
25
26 BBSET sets or clears behavior bits in an .EXE file
27 header. Multi-Tasking MS-DOS uses the behavior
28 bits to determine the level of special
29 compatibility support needed to run the
30 application.
31
32 BBSET will set (if +bitname) or clear (if -
33 bitname) the named behavior bit(s) from the
34 specified files. If the -o switch is specified,
35 BBSET writes a report on the current setting of
36 all the defined behavior bits to stdout after
37 making the requested changes.
38
39 For a list of behavior bits that BBSET knows
40 about, type BBSET without any arguments.
41
42
43 COUNTDOW.EXE - Count down a CPU loop
44
45 countdown number
46
47 Its argument is a number; it counts the number
48 down to 0, at about a 1hz rate. It prints out
49 the countdown. Another CPU loop program like
50 TEXT, but this one terminates when the count
51 reaches 0
52
53
54 DETACH.EXE - Detaches a child process
55
56 detach command [argument ...]
57
58 The command given is run as a background process.
59 Detach prints out the Command Subgroup ID (CSID)
60 which may be used as an argument to KILL to
61 terminate the process.
62
63
64
65
66
67
68
69
70
71 Multi-Tasking MS-DOS Command Guide - Page: 2
72
73 HE_DAEM.EXE - Hard error catcher
74
75 detach he_daem
76
77 Intercepts hard errors, reports them and requests
78 user action. This should always be run in the
79 background for now. Put the above command line in
80 your AUTOEXEC.BAT file if you're not going to use
81 the Session Manager (SM).
82
83
84 KILL.EXE - send a signal to a process
85
86 kill [-nn] [sig=nn] [disp=mm] pid ...
87
88 Sends signal nn with disposition mm to processes
89 mentioned in pid. Defaults to SIGTERM and process
90 tree disposition.
91
92
93 POUND.EXE - Exercise disk I/O system
94
95 pound [t]count filea fileb
96
97 Pound reads sequencially through filea and fileb,
98 reading 512 bytes at a time alternating between
99 the files on each read. When the end of file is
100 read the following read for that file begins at
101 the beginning of the file. If a count is
102 specified without the preceeding "t" then pound
103 reads 512 bytes, count number of times from each
104 file before the program terminates. If "t"
105 preceeds the count value then the files are read
106 for count number of seconds before the program
107 terminates.
108
109
110 SLEEP.EXE - Sleep for a while
111
112 sleep sec[.millisec]
113
114 Sleep will execute a sleep system call for the
115 number of seconds and milliseconds specified.
116 This might be useful in batch files to pause for
117 an interval as opposed to waiting for a user
118 response.
119
120
121 SM.EXE - Session manager
122
123 sm
124
125 Manages multiple processes running on different
126 screens. Uses initialization file SM.INI. This
127
128
129
130
131
132
133
134
135
136
137 Multi-Tasking MS-DOS Command Guide - Page: 3
138
139 program includes the hard error catcher, so don't
140 run HE_DAEM if you're going to use this. See the
141 file SM.DOC for more information.
142
143
144 TEXT.EXE - Loop and print text
145
146 text argument
147
148 CPU loops and prints its argument every 2 CPU
149 seconds or so
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 \ No newline at end of file
diff --git a/v4.0-ozzie/bin/DISK1/CONFIG.SYS b/v4.0-ozzie/bin/DISK1/CONFIG.SYS
new file mode 100644
index 0000000..3d6d514
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/CONFIG.SYS
@@ -0,0 +1,3 @@
1buffers = 40
2files = 20
3break=on
diff --git a/v4.0-ozzie/bin/DISK1/DOS33/FDISK.COM b/v4.0-ozzie/bin/DISK1/DOS33/FDISK.COM
new file mode 100644
index 0000000..b4e3af1
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/DOS33/FDISK.COM
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/DOS33/FORMAT.COM b/v4.0-ozzie/bin/DISK1/DOS33/FORMAT.COM
new file mode 100644
index 0000000..306fc49
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/DOS33/FORMAT.COM
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/DOS33/SYS.COM b/v4.0-ozzie/bin/DISK1/DOS33/SYS.COM
new file mode 100644
index 0000000..d26e982
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/DOS33/SYS.COM
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/IBMBIO.COM b/v4.0-ozzie/bin/DISK1/IBMBIO.COM
new file mode 100644
index 0000000..280a2ef
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/IBMBIO.COM
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/IBMDOS.COM b/v4.0-ozzie/bin/DISK1/IBMDOS.COM
new file mode 100644
index 0000000..a859665
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/IBMDOS.COM
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK1/README b/v4.0-ozzie/bin/DISK1/README
new file mode 100644
index 0000000..4163d4f
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/README
@@ -0,0 +1,67 @@
1
2
3
4
5
6
7 Multi-Taking MS-DOS
8 Beta Test Release 1.00
9
10 Release Notes
11
12
13 Enclosed you will find Microsoft's first beta release
14 of Multi-tasking MS-DOS. This version is based upon MS-DOS
15 Version 2 sources, we will be reimplementing the multi-
16 tasking enhancements on top of Version 3 sources shortly.
17
18 Although we have distributed a bootable disk for the
19 IBM PC, this package can be adapted to any MS-DOS machine.
20 Those manufacturers who are designing IBM compatible ROMs,
21 would be wise to keep multi-tasking in mind. Specifically,
22 this IBM PC implementation has had to hook out the entire
23 disk (both floppy and hard disk) ROM code because after he
24 IBM code set's up the DMA transfer it simply loops in ROM
25 waiting for the interrupt to occur (routine WAIT_INT).
26
27 Problems you may wish to avoid within future ROMs are:
28 1) loading ES with the physical video RAM location
29 (label M3)
30 2) Looping in ROM on Cntrl-NumLock (label K40)
31 3) No way to add special detecting special key
32 strokes which a jump out into RAM after reading
33 the keystroke at KB_INT would avoid
34 4) Not being able to hook the loading of DS to point
35 to DATA (EQU 40H) in numerous routines.
36 Other than these deficiencies the ROM code developed should
37 be very usable.
38
39 By implementing the above suggestions, the size of your
40 BIOS can be reduced since it will not be necessary to
41 duplicate functionality in RAM.
42
43 More detailed specifications of the device driver
44 formats will be forth coming. For the time being you will
45 have to make use of the sample source code for the IBM PC.
46 If you have further questions please contact Microsoft OEM
47 customer support through Technical Assist Requests (TAR).
48
49
50 * * * WARNING * * * WARNING * * * WARNING * * *
51
52 Each copy of this software distribution has been
53 individually serialized to facilitate tracing of
54 unauthorized duplication.
55
56 * * * WARNING * * * WARNING * * * WARNING * * *
57
58
59
60
61
62
63
64
65
66
67 \ No newline at end of file
diff --git a/v4.0-ozzie/bin/DISK1/SM.DOC b/v4.0-ozzie/bin/DISK1/SM.DOC
new file mode 100644
index 0000000..ebbe220
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/SM.DOC
@@ -0,0 +1,199 @@
1
2
3
4
5
6
7 Multi-Tasking MS-DOS
8 Beta Test Release 1.00
9
10 Session Manager
11 User's Guide
12
13
14 Introduction
15
16 The Session Manager(SM) for Multi-Tasking MS-DOS
17 allows you to run up to six programs at one time and switch
18 between them with a couple of keystrokes. Each program's
19 screen is preserved so that it can be restored when you
20 switch back to it. SM also contains the system-wide, Int24
21 Handler.
22
23
24 Initialization
25
26 The first thing SM does when it is started is look for
27 any program initialization information you may have. SM
28 looks for the initialization information in a file named
29 SM.INI in the current directory. Although recommended, no
30 initialization information is needed.
31
32 There are two types of initialization lines:
33 1) define <program key> <program name> [program args]
34 <working directory>
35 2) start <program key>
36
37 "program key" - a printable ascii character, a control
38 character (^A thru ^^), or a function key (F1
39 - F10).
40 "working directory" - a well formed path; i.e., begins
41 with drive letter (d:\).
42
43 Each define line will associate a key with a program.
44 If there is more than one define line using the same key,
45 only the information in the last one is used.
46
47 A start line is optional. If one exists, the program
48 associated with the key on the start line is run as soon as
49 SM finishes initializing. If more than one start line is
50 given, the last one is used.
51
52 This is what a sample initialization file might look like:
53
54 define f1 a:\command.com c:\bin\src
55 define ^z z.exe foo.c a:\foo\bar
56 start f1
57
58
59 Running the Session Manager
60
61 To run Session Manager, just type SM. It does not
62 require any arguments. If there was a start line in the
63
64
65
66
67
68
69
70
71 Session Manager User's Guide - Page: 2
72
73 initialization file, the program associated with the start
74 key will be run. Otherwise, the SM screen will be displayed
75 and you will be prompted for input.
76
77 The SM screen contains a chart that describes each
78 defined program's key, status, arguments, and working
79 directory. There are 3 types of program status:
80
81 1) New - the program has never been run.
82 2) Active - the program has been started.
83 3) Dead - the program has terminated.
84
85 The input choices at this point are to either type a
86 program key or hit the <ESC> button to enter command mode.
87 If you hit a program key, the screen associated with that
88 program will be displayed and the program will
89 start/continue executing. If this is the first time the
90 program has been run, a chdir to the program's working
91 directory is made before it is started. If SM cannot start
92 the program you desired, the SM screen will reappear.
93
94 If the program you chose to run has died, its screen
95 will still be displayed so that you can check its output.
96 That is all you can do while in a dead programs screen
97 except switch back to SM.
98
99 To switch back to SM, hit Alt-F10. Alt-F10 is
100 currently the program key for SM and will be recognized no
101 matter what other programs are running. This is the only
102 program key that works this way. All of the others will
103 only be recognized if SM is running and the SM screen is
104 being displayed.
105
106 Whenever any of SM's children die, their status is
107 changed to dead. You will see the status change the next
108 time the SM screen is displayed. If the program using the
109 current screen dies, you will go back into SM.
110
111
112 Command Mode
113
114 When you enter SM's command mode the prompt "SM command or
115 HELP>" is displayed. The valid SM commands are:
116
117 1) INIT <program key>
118 Initialize the program associated with key so that
119 it can be run again. The program's status is
120 changed to "New" and its screen memory is freed.
121 If the program is active, it is killed before it
122 is initialized.
123
124 2) DEFINE <program key> <program name> [program args]
125 <working directory>
126 Define and run a new program using the supplied
127 information. If the key was previously defined,
128 redefine it.
129
130
131
132
133
134
135
136
137 Session Manager User's Guide - Page: 3
138
139 3) RUN <program key>
140 Run the program associated with key.
141
142 4) RESTART <program key>
143 Restart the program associated with key. This
144 like issuing an INIT and a RUN command.
145
146 5) KILL <program key>
147 Kill the program associated with key. Its status
148 is changed to dead.
149
150 6) HELP
151 Display a help screen.
152
153 7) EXIT
154 Kill all of SM's children and exit SM.
155
156 In all of the above commands, "key" is the printable
157 ascii representation of a programs key. If a command fails,
158 you will either be asked to enter a new command or placed in
159 SM's top level.
160
161
162 Session Manager's Int24 Handler
163
164 Whenever an Int24 occurs, SM's Int24 handler is called.
165 No matter what program is using the screen and no matter
166 which program caused the error, SM's Int24 screen is always
167 displayed. This screen will contain information on the type
168 of Int24 that happened, and the name and pid of the program
169 that caused the error. You will then be prompted for one of
170 the valid actions for this type of error. After the action
171 typed in has been taken, you are returned to the screen you
172 were using before the Int24.
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 \ No newline at end of file
diff --git a/v4.0-ozzie/bin/DISK1/SM.INI b/v4.0-ozzie/bin/DISK1/SM.INI
new file mode 100644
index 0000000..bf7dfc8
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK1/SM.INI
@@ -0,0 +1,2 @@
1define F7 a:\command.com a:\
2define F8 a:\command.com c:\
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/ANSI.INC b/v4.0-ozzie/bin/DISK2/BIOS/ANSI.INC
new file mode 100644
index 0000000..37e661b
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/ANSI.INC
@@ -0,0 +1,573 @@
1; Termcap description of capabilities:
2
3;ibmans4:mtcon:IBM PC with V4.0 ANSI driver:\
4; :al=\E[L:am:bs:ce=\E[K:cl=\E[2J\E[H:cm=\E[%;%H:co#80:\
5; :dl=\E[M:do=\E[B:ho=\E[H:li#24:mi:nd=\E[C:\
6; :ms:pt:se=\E[m:so=\E[1;36m:up=\E[A:\
7; :kb=^h:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:kh=\E[H:kn#8:\
8; :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\
9; :k6=\EP:k7=\EQ:k8=\ER:
10
11CMDTABL DB 'A'
12 DW CUU ;CUrsor Up
13 DB 'B'
14 DW CUD ;CUrsor Down
15 DB 'C'
16 DW CUF ;CUrsor Forward
17 DB 'D'
18 DW CUB ;CUrsor Back
19 DB 'H'
20 DW CUP ;CUrsor Position
21 DB 'J'
22 DW ED ;Erase in Display
23 DB 'K'
24 DW EL ;Erase in Line
25 DB 'L'
26 DW IL ;Insert Line
27 DB 'M'
28 DW xDL ;Delete Line
29;; DB 'R'
30;; DW CPR ;Cursor Postion Report
31 DB 'f'
32 DW HVP ;Horizontal and Vertical Position
33 DB 'h'
34 DW SM ;Set Mode
35 DB 'l'
36 DW RM ;Reset Mode
37 DB 'm'
38 DW SGR ;Select Graphics Rendition
39;; DB 'n'
40;; DW DSR ;Device Status Report
41 DB 's'
42 DW SCP ;Save Cursor Position
43 DB 'u'
44 DW RCP ;Restore Cursor Position
45 DB 00
46
47; Graphic Rendition modes: parameter, mask, set
48GRMODE DB 00,00000000B,00000111B ; all off
49 DB 01,11111111B,00001000B ; bold (increased intensity)
50 DB 04,11111000B,00000001B ; underscore
51 DB 05,11111111B,10000000B ; blink
52 DB 07,11111000B,01110000B ; reverse video
53 DB 08,10001000B,00000000B ; concealed
54 DB 30,11111000B,00000000B ; foreground colors ...
55 DB 31,11111000B,00000100B
56 DB 32,11111000B,00000010B
57 DB 33,11111000B,00000110B
58 DB 34,11111000B,00000001B
59 DB 35,11111000B,00000101B
60 DB 36,11111000B,00000011B
61 DB 37,11111000B,00000111B
62 DB 40,10001111B,00000000B ; background colors ...
63 DB 41,10001111B,01000000B
64 DB 42,10001111B,00100000B
65 DB 43,10001111B,01100000B
66 DB 44,10001111B,00010000B
67 DB 45,10001111B,01010000B
68 DB 46,10001111B,00110000B
69 DB 47,10001111B,01110000B
70 DB 0FFH
71
72; Set/Reset Modes: indexed by (SelChar-'<'*8) + (PARAM0 AND 7)
73SRMODE DW 0,0,0,0,0,0,0,0 ; SelChar '<'
74 DW 1,1,1,1,1,1,1,WRAP ; SelChar '='
75 DW 0,EnaL25,0,0,0,0,0,0 ; SelChar '>'
76 DW 0,0,0,0,0,0,0,WRAP ; SelChar '?'
77
78PAGE
79; The following are duplicates of the same variables from the ROM
80;
81;* WARNING - the following two variables are accessed as a word
82MODE DB 3
83MAXCOL DB 79
84IF LINE25 ; special treatment of line 25?
85maxrow equ 24
86ELSE
87maxrow equ 25
88ENDIF
89;* WARNING - the following two variables are accessed as a word
90COL DB 0 ; current column
91ROW DB 0 ; current row
92
93
94AnsiState LABEL BYTE ; the following must be saved on a screen swap
95WRAP DB 1 ; 0 = NO WRAP, 1 = WRAP
96EnaL25 DB 0 ; 0 = 25th line disabled, 1 = enabled
97STATE DW S1
98SAVCR DW 0 ; saved cursor position
99;* WARNING - the following two variables are accessed as a word
100SelChar DB 0 ; <,=,> or ? private use indicators
101PRMCNT LABEL BYTE ; number of parameters for command
102PRMCNTW DW 0
103NUMPARAM equ 5 ; max. number of parameters
104PARAM DB NUMPARAM DUP (?) ; buffer for command parameters
105;* WARNING - the following two variables are accessed as a word
106attrw LABEL WORD
107ATTR DB 00000111B ;CHARACTER ATTRIBUTE
108BPAGE DB 0 ;BASE PAGE
109
110AnsiSize equ ($-AnsiState)
111
112IF (AnsiSize GT TermSize)
113 .RADIX 0 ; ERROR - Terminal state not big enough
114ENDIF
115
116;-------------------------------------------------------------
117;
118; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE
119;
120base dw 0b800h
121screen_seg dw 00000h
122
123chrout: cmp al,13 ; carriage return?
124 ja outchr
125 jnz trylf
126 mov [col],0
127;; jmp short setit
128 jmp setit
129
130trylf: cmp al,10 ; line feed?
131 jz lf
132 cmp al,7 ; bell?
133 jnz trytab
134torom:
135 mov bx,[attrw]
136 and bl,7
137 mov ah,14
138 int 10h
139ret5: ret
140
141trytab:
142 cmp al,9 ; tab?
143 jnz tryback
144 mov al,[col]
145 add al,8
146 mov ah,al
147 and ah,7
148 sub al,ah
149 cmp al,[maxcol]
150 jb tunder
151 mov al,[maxcol]
152tunder:
153 mov [col],al
154 jmp short setit
155
156tryback:
157 cmp al,8 ; backspace?
158 jnz outchr
159 cmp [col],0
160 jz ret5
161 dec [col]
162 jmp short setit
163
164outchr:
165 mov bx,[attrw]
166 mov cx,1
167 mov ah,9
168 int 10h
169 inc [col]
170 mov al,[col]
171 cmp al,[maxcol]
172 jbe setit
173 cmp [wrap],1
174 jz outchr1
175 dec [col]
176 ret
177outchr1:
178 mov [col],0
179lf: cmp [row],(maxrow-1)
180 ja setit ; on line 25, don't move
181 jz lf1 ; on 24th line, scroll
182 inc [row]
183 jmp short setit
184lf1: call scroll
185
186setit: mov dx,word ptr col
187 mov bh,[bpage]
188 mov ah,2
189 int 10h
190 ret
191
192scroll: mov al,mode
193 cmp al,2
194 jz myscroll
195 cmp al,3
196 jz myscroll
197IF LINE25
198 xor cx,cx ; from 0,0
199 mov dh,(maxrow-1) ; to maxrow-1,maxcol
200 mov dl,maxcol
201 mov bh,attr
202 mov ax,0601h ; scroll up one line
203 int 10h
204 ret
205ELSE
206 mov al,10
207 jmp torom
208ENDIF
209myscroll:
210 mov bh,[attr]
211 mov bl,' '
212 mov bp,80
213 mov ax,[base]
214 add ax,[screen_seg]
215 mov es,ax
216 mov ds,ax
217 xor di,di
218 mov si,160
219 mov cx,(maxrow-1)*80
220 cld
221
222; This code will never get executed since we get here when
223; mode = 2 or 3 only.
224;; cmp cs:[base],0b800h
225;; jz colorcard
226
227;; rep movsw
228;; mov ax,bx
229;; mov cx,bp
230;; rep stosw
231;; jmp short sret
232
233;;colorcard:
234 mov dx,3dah
235wait2: in al,dx
236 test al,8
237 jz wait2
238 mov al,25h
239 mov dx,3d8h
240 out dx,al ;turn off video
241 rep movsw
242 mov ax,bx
243 mov cx,bp
244 rep stosw
245 mov al,29h
246 mov dx,3d8h
247 out dx,al ;turn on video
248sret: push cs
249 pop ds
250 ret
251
252
253CharOut: PUSH AX ; Main entry point
254 PUSH BX
255 PUSH CX
256 PUSH DX
257 PUSH SI
258 PUSH DI
259 PUSH ES
260 PUSH BP
261
262 MOV [base],0B800H
263 XCHG AX,SI ; SAVE CHARACTER TO STUFF
264 MOV AX,40H ; POINT TO ROS BIOS
265 MOV DS,AX
266 MOV AX,DS:[49H] ; AL=MODE, AH=MAX COL
267 DEC AH ; ANSI NEEDS 0-79 OR 0-39
268 MOV WORD PTR CS:[MODE],AX ; SAVE MODE AND MAX COL
269 CMP AL,7
270 JNZ NOT_BW
271 MOV WORD PTR CS:[base],0B000H
272NOT_BW: MOV AL,DS:[62H] ; GET ACTIVE PAGE
273 MOV CS:[BPAGE],AL
274 CBW
275 ADD AX,AX
276 MOV BX,AX
277 MOV AX,DS:[BX+50H] ; AL=COL, AH=ROW
278 MOV WORD PTR CS:[COL],AX ; SAVE ROW AND COLUMN
279 MOV AX,DS:[4EH] ; GET START OF SCREEN SEG
280 MOV CL,4
281 SHR AX,CL ; CONVERT TO A SEGMENT
282 PUSH CS
283 POP DS
284 MOV [screen_seg],AX
285 XCHG AX,SI ; GET BACK CHARACTER IN AL
286
287 CALL VIDEO
288 POP BP
289 POP ES
290 POP DI
291 POP SI
292 POP DX
293 POP CX
294 POP BX
295 POP AX
296 RET
297
298
299;----------------------------------------------------------
300;
301; OUTPUT SINGLE CHAR IN AL TO VIDEO DEVICE
302;
303VIDEO: MOV SI,OFFSET STATE
304 JMP [SI]
305
306S2: CMP AL,'['
307 JZ S22
308 JMP S1
309S22: MOV WORD PTR [SI],OFFSET S30
310 XOR BX,BX
311 MOV WORD PTR SelChar,BX
312 MOV WORD PTR PARAM,BX
313 JMP SHORT S3B
314
315S30: CMP AL,'?' ; experimental use selector (SM/RM)?
316 JA S7
317 mov SelChar,al
318 MOV WORD PTR [SI],OFFSET S3
319 cmp al,'<'
320 jae S3B
321
322S3: CMP AL,';'
323 JNZ S3C
324S3A: INC PRMCNT
325S3B: CALL GETPTR
326 XOR AX,AX
327 MOV WORD PTR [BX],AX ;DEFAULT VALUE IS ZERO
328 RET
329
330S3C: CMP AL,'0'
331 JB S3D
332 CMP AL,'9'
333 JA S7
334 CALL GETPTR
335 SUB AL,'0'
336 XCHG AL,BYTE PTR [BX]
337 MOV AH,10
338 MUL AH ;*10
339 ADD BYTE PTR [BX],AL ;MOVE IN DIGIT
340 RET
341
342S3D:
343;; CMP AL,'"' ;BEGIN QUOTED STRING
344;; JZ S3E
345;; CMP AL,"'"
346 JNZ S7
347;;S3E: MOV WORD PTR [SI],OFFSET S4
348;; MOV [INQ],AL
349S3RET: RET
350
351;
352; ENTER QUOTED STRINGS
353;
354
355;;S4: CMP AL,[INQ] ;CHECK FOR STRING TERMINATOR
356;; JNZ S4A
357;; DEC PRMCNT ;TERMINATE STRING
358;; MOV WORD PTR [SI],OFFSET S3
359;; RET
360
361;;S4A: CALL GETPTR
362;; MOV BYTE PTR [BX],AL
363;; MOV WORD PTR [SI],OFFSET S4
364;; JMP S3A
365;
366; LOOK FOR ANSI COMMAND SPECIFIED IN AL
367;
368
369S7: MOV BX,OFFSET CMDTABL-3
370;
371S7A: ADD BX,3
372 CMP BYTE PTR [BX],0
373 JZ S1B
374 CMP BYTE PTR [BX],AL
375 JNZ S7A
376;
377S7B: MOV AX,WORD PTR [BX+1] ;AX = JUMP ADDRESS
378 MOV BX,OFFSET PARAM
379 MOV DL,BYTE PTR [BX]
380 XOR DH,DH ;DX = FIRST PARAMETER
381 MOV CX,DX
382 OR CX,CX
383 JNZ S7C
384 INC CX ; if DX=0, CX=1 else CX = DX
385S7C: JMP AX ;AL = COMMAND
386
387S1: CMP AL,1Bh ;ESCAPE SEQUENCE?
388 JNZ S1B
389 MOV WORD PTR [SI],OFFSET S2
390 RET
391
392S1B: CALL CHROUT
393S1A: MOV WORD PTR [STATE],OFFSET S1
394 RET
395
396MOVCUR: CMP BYTE PTR [BX],AH
397 JZ SETCUR
398 ADD BYTE PTR [BX],AL
399 LOOP MOVCUR
400SETCUR: MOV DX,WORD PTR COL
401 XOR BX,BX
402 MOV AH,2
403 int 10h ; call ROM
404 JMP S1A
405
406HVP:
407CUP:
408IF LINE25
409 CMP CL,(maxrow+1)
410 jb cup3 ; new row is 24 or less
411 JA SETCUR ; error - 26 or greater
412 cmp EnaL25,0 ; else 25, is it allowed?
413 jz SETCUR
414cup3:
415ELSE
416 CMP CL,maxrow
417 JA SETCUR
418ENDIF
419 MOV AL,MAXCOL
420 MOV CH,BYTE PTR [BX+1]
421 OR CH,CH
422 JZ CUP1
423 DEC CH
424CUP1: CMP AL,CH
425 JA CUP2
426 MOV CH,AL
427CUP2: XCHG CL,CH
428 DEC CH
429 MOV WORD PTR COL,CX
430 JMP SETCUR
431
432CUF: MOV AH,MAXCOL
433 MOV AL,1
434CUF1: MOV BX,OFFSET COL
435 JMP MOVCUR
436
437CUB: MOV AX,00FFH
438 JMP CUF1
439
440CUU: MOV AX,00FFH
441CUU1: MOV BX,OFFSET ROW
442 JMP MOVCUR
443
444CUD: MOV AX,(maxrow-1)*256+1
445IF LINE25
446 cmp ah,[row] ; at bottom of screen?
447 ja SETCUR
448ENDIF
449 JMP CUU1
450
451SCP: MOV AX,WORD PTR COL
452 MOV SAVCR,AX
453 JMP SETCUR
454
455RCP: MOV AX,SAVCR
456IF LINE25
457 cmp ch,maxrow
458 jb rcp1
459 cmp EnaL25,0
460 jz rcp2
461ENDIF
462rcp1: MOV WORD PTR COL,AX
463rcp2: JMP SETCUR
464
465SGR: XOR CX,CX
466 XCHG CL,PRMCNT
467 CALL GETPTR
468 INC CX
469SGR1: MOV AL,BYTE PTR [BX]
470 PUSH BX
471 MOV BX,OFFSET GRMODE
472SGR2: MOV AH,BYTE PTR [BX]
473 ADD BX,3
474 CMP AH,0FFH
475 JZ SGR3
476 CMP AH,AL
477 JNZ SGR2
478 MOV AX,WORD PTR [BX-2]
479 AND ATTR,AL
480 OR ATTR,AH
481SGR3: POP BX
482 INC BX
483 LOOP SGR1
484 JMP SETCUR
485
486ED:
487IF LINE25
488 cmp row,maxrow ; on 25th line?
489 je EL ; yes, treat like Erase in Line
490ENDIF
491 xor cx,cx
492 mov dl,maxcol
493 mov dh,(maxrow-1)
494 cmp param,1 ; which subcommand?
495 ja el2 ; all
496 jb ed1
497 mov dh,row ; to beginning
498 dec dh
499 jle EL
500 jmp short ed2
501ed1: mov ch,row ; to end
502 inc ch
503 cmp ch,dh
504 jae EL
505ed2: mov bh,attr
506 MOV AX,0600H
507 int 10h ; call ROM
508
509EL: MOV CX,WORD PTR COL
510 MOV dx,cx
511 mov al,param
512 inc al ; 0,1,2 => 1,2,3
513 test al,1 ; to end?
514 je el1
515 mov dl,maxcol
516el1: test al,2 ; to beginning?
517 je el2
518 mov cl,0
519el2: mov bh,attr
520 mov ax,0600H
521 int 10h
522S1A_j: jmp S1A
523
524IL: mov ah,7 ; scroll down
525 jmp short dl1
526
527xDL: mov ah,6 ; scroll up
528dl1: mov al,cl ; number of lines
529 mov ch,row
530 xor cl,cl
531 mov dh,(maxrow-1)
532 mov dl,maxcol
533 mov bh,attr
534 int 10h
535 jmp S1A_j
536
537RM: XOR CL,CL
538 JMP SHORT SM1
539
540SM: MOV CL,1
541SM1: mov bl,SelChar ; get selection character
542 sub bl,'<' ; adjust
543 jb S1A_j ; less than '<'
544 cmp bl,4
545 jae S1A_j ; greater than '?'
546 xor bh,bh
547 shl bx,1
548 shl bx,1
549 shl bx,1
550 MOV AL,DL
551 CMP AL,7
552 JA S1A_j
553 or bl,al
554 shl bx,1
555 mov bx,SRMODE[bx] ; get function indicator
556 cmp bx,1 ; no or special function?
557 jb S1A_j
558 jz SM2 ; sets screen mode
559 MOV [bx],CL
560 JMP S1A_j
561
562SM2: MOV AH,0
563 int 10h ; call ROM
564 JMP S1A_j
565
566; GetPtr - get a pointer to the current parameter
567GETPTR: MOV BX,PRMCNTW
568 CMP BX,NUMPARAM
569 JB GET1
570 DEC PRMCNT
571 JMP GETPTR
572GET1: ADD BX,OFFSET PARAM
573 RET
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/BIOSOBJ.MAK b/v4.0-ozzie/bin/DISK2/BIOS/BIOSOBJ.MAK
new file mode 100644
index 0000000..e69d153
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/BIOSOBJ.MAK
@@ -0,0 +1,20 @@
1ibmbio.obj: ibmbio.asm defdbug.inc bugcode.inc
2 masm ibmbio;
3
4ibmmtcon.obj: ibmmtcon.asm ansi.inc defdbug.inc
5 masm ibmmtcon;
6
7ibmdsk.obj: ibmdsk.asm defdbug.inc
8 masm ibmdsk;
9
10sysini.obj: sysini.asm dossym.inc devsym.inc syscalls.inc
11 masm sysini;
12
13sysimes.obj: sysimes.asm
14 masm sysimes;
15
16ibmbio.exe: ibmbio.obj ibmmtcon.obj ibmdsk.obj sysini.obj sysimes.obj
17 link ibmbio ibmmtcon ibmdsk sysini sysimes,ibmbio,ibmbio/map;
18
19ibmbio.com: ibmbio.exe
20 exe2bin ibmbio ibmbio.com
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/BOOTPACH.EXE b/v4.0-ozzie/bin/DISK2/BIOS/BOOTPACH.EXE
new file mode 100644
index 0000000..378331e
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/BOOTPACH.EXE
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC b/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC
new file mode 100644
index 0000000..4a87725
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC
@@ -0,0 +1,553 @@
1;*** Bugcode.inc - Debug code for including into sysini.asm and ibmbio.asm
2;
3; Can't link in via buglib due to memory and relocation games played
4; by these modules. Each gets a private, local-only copy of these
5; modules.
6
7
8IFDEF DEBUGFLG
9
10
11;** DPRINTF _ Debug Printf
12;
13; Dprintf is a kernel debug print formatting package. It is intended
14; to produce conviently formatted output.
15;
16; Dprintf is called, indirectly, by a macro:
17;
18; DEBUG n,m,"string",<a1,...,an>
19;
20; string = format string
21; a1 = first argument
22; an = last argument
23;
24; The format string is an ASCIZ string which can contain 2 types of
25; specifications: data-format specifications and literal characters.
26; Data format specifications always begin with a '$' character; all
27; characters not part of a data format specification are treated as
28; literal characters.
29;
30; Literal characters
31; - any character not part of a format specification. Special
32; non-printing characters are:
33; \n - CRLF
34; \t - tab
35; \b - bell
36; \\ - \
37; \$ - $
38;
39; Format Specifications
40;
41; A format specification takes the form:
42; $ [@] <char>
43;
44; where <char> =
45;
46; x - print argument as a hex word
47; d - print argument as decimal word
48; c - print argument as ascii character
49; b - print argument as hex byte
50; For each of the above formats, the supplied argument
51; is a 16-bit word - the value to be printed. The optional @
52; (described below) allows a segmented address to be supplied,
53; instead.
54;
55; s[nn] - print argument as asciz string; if optional decimal
56; argument follows the format character this specifys
57; a maximum string length. Non printing characters are
58; printed in the form \nnn where "nnn" is the octal byte
59; value.
60; Note that this format character cannot be directly
61; followed by a digit unless that digit is to be taken
62; as the start of a length argument.
63;
64; Bnn - print argument as hex bytes. The required following
65; decimal argument is the number of bytes to print.
66;
67; Both of these formats take a long address as their argument.
68; The '@' character is thus invalid for these formats.
69;
70; WARNINGS
71; As befitting a debug routine, DPRINTF does not have a whole lot
72; of "failsafe" code in it. Supplying screwed up formats can
73; muck things up. Specifically:
74; The @ argument must NOT be specified with the 's' or 'B'
75; format
76; A string/byte-length argument of 0 is taken as 65536
77; The string "%% BAD FMT %%" appears in the output when
78; 1) an illegal format specifier is given, or
79; 2) the B format is given a 0 or missing length
80;
81; ENTRY (sp+n ) = address of format string (offset from return cs value)
82; (sp+n-2) = first argument word
83; (sp+n-4) = second argument word
84; .
85; (sp+4 ) = last argument word
86; (sp+2 ) = seg of return address
87; (sp ) = offset of return address
88; (bp) = offset of format string on the stack
89; EXIT none
90; USES flags
91
92 PUBLIC DPRINTF
93DPRINTF PROC near
94
95 push ds
96 push es
97 push bp
98 push di
99 push si
100 push dx
101 push cx
102 push bx
103 push ax ; save registers
104 cld
105
106 mov si,[bp] ; get address of format string
107 sub bp,2
108 mov bx,sp
109 mov ds,ss:20[bx] ; (ds:si) = address of format string
110 push cs
111 pop ds
112
113; Scan format string for next character
114;
115; (ds:si) = address of format string
116; (ss:bp) = address of next argument
117
118dpf1: lodsb ; (al) = format string byte
119 and al,al
120 je dpf3 ; all done
121 cmp al,'$'
122 je dpf4 ; is data escape
123 cmp al,'\'
124 jnz dpf2 ; got the character
125
126; it's an "\" escape code - crack the argument character
127
128 lodsb
129 and al,al
130 je dpf3 ; all done, ignore hanging \
131 xchg ah,al
132 mov al,0Ch
133 cmp ah,'n'
134 jne dpf1$5 ; not \n
135 mov al,0dH
136 call putchar
137 mov al,0aH
138 jmp SHORT dpf2 ; print LF
139
140dpf1$5: cmp ah,'t'
141 mov al,9
142 je dpf2 ; is \t
143 cmp ah,'b'
144 mov al,7
145 je dpf2 ; is \b
146 xchg ah,al
147dpf2: call putchar
148 jmp dpf1
149
150; have the end of the format string - exit
151
152dpf3: pop ax
153 pop bx
154 pop cx
155 pop dx
156 pop si
157 pop di
158 pop bp
159 pop es
160 pop ds
161 ret
162
163
164;* Have a '$' character - is data format escape
165;
166; Get address of data into es:di
167;
168; (bp) = address of data value
169
170dpf4: mov di,bp
171 push ss
172 pop es ; (es:di) = address of data value
173 sub bp,2 ; point to next argument
174 lodsb ; (al) = format specifier
175 cmp al,'@'
176 jne dpf5 ; not an indirect flag
177 les di,[bp]
178 sub bp,2 ; have an extra 2 for @
179 lodsb
180dpf5: cmp al,'x'
181 jne dpfd1 ; not 'x'
182
183; is 'x' format - print hex word
184
185 mov ax,es:[di]
186 call THW ; type hex word
187 jmp dpf1
188
189dpfd1: cmp al,'d'
190 jnz dpfc1 ; not 'd'
191
192; is 'd' format - print decimal word
193
194 mov ax,es:[di]
195 call TDW ; type decimal word
196 jmp dpf1
197
198dpfc1: cmp al,'c'
199 jne dpfb1
200
201; is 'c' format - print character
202
203 mov al,es:[di]
204 call putchar
205 jmp dpf1
206
207dpfb1: cmp al,'b'
208 jne dpfs1
209
210; is 'b' format - print hex byte
211
212 mov al,es:[di]
213 call THB ; type hex byte
214 jmp dpf1
215
216dpfs1: cmp al,'s'
217 jne dpfbb1
218
219; is 's' format - print ASCIZ string. First, check for
220; optional decimal limit
221
222 public SSB
223SSB: sub cx,cx ; set 65536 limit
224 les di,[bp] ; (es:DI) = fwa of string
225 sub bp,2 ; argument to 's' was two words
226 mov al,[si]
227 cmp al,'0'
228 jb dpfs2 ; not decimal
229 cmp al,'9'
230 ja dpfs2 ; not decimal
231 call atod ; (ax) = decimal value, (ds:si) updated
232 xchg cx,ax
233
234; print asciz string at es:di, max of (cx) characters
235; (cx) = 0 means max of 65536
236;
237; Other sections of code in dpf jump here to print strings
238
239dpfs2: mov al,es:[di]
240 inc di
241 and al,al
242 je dpfs3
243 call putchar
244 loop dpfs2 ; continue if not at limit
245dpfs3: jmp dpf1
246
247dpfbb1: cmp al,'B'
248 je dpfbb2 ; is 'B' format
249
250; error in format code - print message
251
252dpferr: push cs
253 pop es
254 mov di,OFFSET dpfa ; (es:di) = error message
255 sub cx,cx
256 jmp dpfs2
257
258dpfa: DB '%% BAD FMT %%',0
259
260; have B format
261
262dpfbb2: call atod ; (ax) = length specifier
263 jc dpferr ; number not there - error
264 xchg cx,ax
265 jcxz dpferr ; number is 0 - error
266 les di,[bp] ; (es:DI) = fwa of string
267 sub bp,2 ; argument to 's' was two words
268dpfbb3: mov al,es:[di]
269 call THB ; type hex byte
270 mov al,' '
271 call putchar ; space em out
272 inc di
273 loop dpfbb3 ; do em all
274 jmp dpf1
275
276DPRINTF ENDP
277
278
279;** THB - Type Hex Byte
280;
281; THB types a hex byte (via "putchar")
282;
283; ENTRY (AL) = byte
284; EXIT none
285; USES ax, flags
286
287THBA DB '0123456789abcdef'
288
289 PUBLIC THB
290THB PROC near
291
292 push ax
293 shr al,1
294 shr al,1
295 shr al,1
296 shr al,1
297 and ax,0fH
298 xchg bx,ax
299 mov bl,CS:THBA[bx]
300 xchg ax,bx
301 call putchar ; put first character
302 pop ax
303 and ax,0fH
304 xchg bx,ax
305 mov bl,CS:THBA[bx]
306 xchg ax,bx
307 call putchar
308 ret
309
310THB ENDP
311
312
313
314
315;** THW - Type Hex Word
316;
317; THW types a word in hex (via "putchar")
318;
319; ENTRY (AX) = word
320; EXIT none
321; USES AX, flags
322
323 PUBLIC THW
324THW PROC near
325
326 push ax
327 xchg ah,al
328 call THB
329 pop ax
330 call THB
331 ret
332
333THW ENDP
334
335
336
337;** TDW - Type Decimal Word
338;
339; TDW types (via "putchar") the unsigned decimal representation
340; of a 16-bit unsigned integer. Only significant digits are
341; printed; if the number is 0 a "0" is printed.
342;
343; ENTRY (AX) = number
344; EXIT none
345; USES AX, flags
346
347 PUBLIC TDW
348TDW PROC near
349
350 push cx ; preserve registers
351 push dx
352 mov cx,10
353 call tdw$ ; recurse cracking digits
354 pop dx
355 pop cx
356 ret
357
358TDW ENDP
359
360
361;* tdw$ - crack number recursively
362;
363; tdw$ cracks the least significant decimal digit. If there
364; are no higher-significant digits, print and return.
365; else, recurse for higher digits
366;
367; (AX) = value
368; (CX) = 10
369
370tdw$ PROC NEAR
371
372 sub dx,dx
373 div cx ; (ax) = quotient, (dx) = remainder
374 and ax,ax
375 jz tdw$1 ; this is highest-order, do it
376 push dx
377 call tdw$
378 pop dx
379tdw$1: xchg ax,dx
380 add al,'0'
381 call putchar
382 ret
383
384TDW$ ENDP
385
386
387
388;** ATOD - Convert ASCII string to decimal number
389;
390; ATOD is called to convert an ascii string of digits to a
391; decimal number. Digits are converted until we run out of them.
392;
393; ENTRY (DS:SI) = address of first digit
394; EXIT 'C' clear if OK
395; (AX) = value
396; (SI) updated to first non-digit
397; 'C' set if error - no digits, or result >65535
398; (DS:SI) points to error character
399; USES AX, SI, FLAGS
400
401 PUBLIC ATOD
402ATOD PROC near
403
404 push dx
405 push cx ; save registers
406 mov al,[si]
407 sub al,'0'
408 jc atod9 ; error - no digits
409 cmp al,10
410 cmc
411 jc atod9 ; error - no digits
412 sub ax,ax ; clear accumulator
413 mov cx,10 ; base 10
414
415; crack next digit
416;
417; (AX) = number accumulated so near
418; (CX) = 10
419; (DS:SI) = next character
420
421atod1: xchg dx,ax ; keep accum in dx for a while
422 lodsb ; (al) = character
423 sub al,'0'
424 jc atod7 ; not digit - all done
425 cmp al,9
426 ja atod7 ; not digit - all done
427 sub ah,ah ; (ax) = digit value (0 - 9)
428 push ax
429 xchg ax,dx
430 mul cx ; (ax) = 10*accum
431 pop dx ; (dx) = digit to add
432 jo atod8 ; overflow
433 add ax,dx
434 jmp atod1 ; go back for more
435
436; Done with number, all OK
437;
438; (dx) = number
439; (ds:si) = address+1 of first unused character
440
441atod7: clc
442
443; Done with number, error
444; 'C' set
445
446atod8: dec si ; backup over non-decimal (or error) char
447atod9: pop cx
448 xchg ax,dx ; (ax) = number iff no error
449 pop dx ; restore registers
450 ret ; exit
451
452ATOD ENDP
453
454;** putchar - put a character on the console
455;
456; ENTRY (al) = character
457; EXIT none
458; USES ax,flags
459
460
461UR_DAT = 02f8H ; COM1 = 03f8H, COM2 = 02f8H
462UR_IEN = UR_DAT+1 ; Interrupt enable
463UR_IER = UR_DAT+2 ; interrupt ID
464UR_LCR = UR_DAT+3 ; line control registers
465UR_MCR = UR_DAT+4 ; modem control register
466UR_LSR = UR_DAT+5 ; line status register
467UR_MSR = UR_DAT+6 ; modem status regiser
468UR_DLL = UR_DAT ; divisor latch least sig
469UR_DLM = UR_DAT+1 ; divisor latch most sig
470
471iflag DB 0 ; != 0 when initialized 8250
472
473;* inchr - input character
474;
475; EXIT 'z' set if no character
476; 'z' clear if char
477; (al) = char
478
479inchr: mov dx,UR_LSR
480 in al,dx
481 and al,1
482 jz inchr1
483 mov dx,UR_DAT
484 in al,dx
485 and al,07fh
486inchr1: ret
487
488
489 PUBLIC putchar
490putchar PROC NEAR
491 pushf
492 cli
493 push dx
494 push cx
495 push bx
496 push ax ; (al) = character
497 test iflag,255
498 jnz putc1 ; is initialized
499 inc iflag
500
501; program the usart
502
503 mov dx,UR_LCR
504 mov al,80h
505 out dx,al ; command it
506 sub al,al
507 mov dx,UR_DLM
508 out dx,al
509 mov dx,UR_DLL
510 mov al,12 ; 9600 baud = 12, 19.2 Kbaud = 6
511 out dx,al
512 mov al,3
513 mov dx,UR_LCR
514 out dx,al ; command normal mode
515
516; see if CTL-Q or CTL-S
517
518putc1: pushf
519 cli
520 call inchr
521 jz putc3 ; no characters incomming
522 cmp al,19 ; ctl-S?
523 jnz putc3 ; no, ignore
524
525; have ctl-s. wait till we see ctl-Q
526
527putc2: call inchr
528 jz putc2
529 cmp al,17
530 jnz putc2
531
532putc3: popf
533 mov dx,UR_LSR
534putc4: in al,dx
535 test al,020h
536 jz putc4
537
538; ready. crank it out!
539
540 mov dx,UR_DAT
541
542 pop ax
543 out dx,al
544
545 pop bx
546 pop cx
547 pop dx
548 popf
549 ret
550
551putchar ENDP
552
553ENDIF
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/DEFDBUG.INC b/v4.0-ozzie/bin/DISK2/BIOS/DEFDBUG.INC
new file mode 100644
index 0000000..590e376
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/DEFDBUG.INC
@@ -0,0 +1,122 @@
1;** DEFDBUG.ASM - Debugging Macro Definitions
2;
3;
4; DEBUG n,m,<format string>, <arg list>
5;
6;
7
8.sall
9
10DEBUG MACRO N,M,string,args
11 local b,c
12 IFDEF DEBUGFLG
13 pushf
14 DEBUGTST N,M
15 jz b
16 push ax
17 push bp
18 call c ;; push address of string
19 DB '&string',0
20c: mov bp,sp
21; IFNB <args>
22 IRP Y,<args>
23 IFIDN <Y>,<ax>
24 push 4[bp]
25 ELSE
26 IFIDN <Y>,<AX>
27 push 4[bp]
28 ELSE
29 IFIDN <Y>,<bp>
30 push 2[bp]
31 ELSE
32 IFIDN <Y>,<BP>
33 push 2[bp]
34 ELSE
35 mov ax,Y
36 push ax
37 ENDIF
38 ENDIF
39 ENDIF
40 ENDIF
41 ENDM
42; ENDIF
43 call DPRINTF
44 mov sp,bp
45 pop ax ;; discard format string offset
46 pop bp
47 pop ax
48b: popf
49 ENDIF
50ENDM
51
52
53
54
55;** ERRNZ - generate assembly error if arg != 0
56;
57
58ERRNZ MACRO EXPR
59 IF1
60 IFE expr
61 ELSE
62 RADIX 0 ; CONDITION NOT MET - ERROR
63 ENDIF
64 ENDIF
65 ENDM
66
67
68;** DBBEG - Start debugging range
69;
70
71DBBEG MACRO N,M
72 LOCAL lab
73 IFDEF DEBUGFLG
74 pushf
75 DEBUGTST N,M
76 jnz lab ;; am to do it
77 DBJMP %DBCNT
78lab:
79 ENDM
80
81
82
83DBJMP MACRO N
84 jmp DBLAB&N
85 ENDM
86
87
88;** DEBUGTST - Test Debug Flags
89;
90; DEBUGTST n,m
91;
92; Where N and M are bit masks.
93;
94; If one or more of the bits in N is set in the high byte
95; of BUGBITS, and one or more of the bits in M is set in
96; the low byte of BUGBITS then clear the Z flag.
97;
98; In other words:
99;
100; If both masks show a "hit" clear 'Z' else set 'Z'
101;
102; USES FLAGS
103
104DEBUGTST MACRO N,M
105 LOCAL A
106 test BYTE PTR BUGBITS,n
107 jz A
108 test BYTE PTR BUGBITS+1,m
109A:
110 ENDM
111
112DBEND MACRO
113 DBLAB %DBCNT
114DBCNT = DBCNT+1
115 popf
116 ENDM
117
118DBLAB MACRO N
119DBLAB&N:
120 ENDM
121
122 DBCNT = 1
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
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.OBJ
new file mode 100644
index 0000000..28d0720
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMBIO.OBJ
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.ASM b/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.ASM
new file mode 100644
index 0000000..47869d0
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.ASM
@@ -0,0 +1,2551 @@
1TITLE DISK - MS-DOS 4.0 disk drivers for IBM
2NAME DISK
3
4 PAGE ,132
5
6;DEBUGFLG=1
7
8.xlist
9 INCLUDE DEFDBUG.INC
10.list
11
12; Constants
13
14ErrLim= 5 ; Number of retries on error
15
16; Floppy delay constants
17
18DelayLoad= 35 ; 35 milliseconds to load head
19
20; Constants for floppy disk controller
21
22Rate99= 000H ; Step rate 96tpi disk in 96tpi drive
23Rate49= 001H ; Step rate 48tpi disk in 96tpi drive
24Rate44= 002H ; Step rate 48tpi disk in 48tpi drive
25
26; Commands to floppy disk controller
27
28FD_CRESET= 007H ; Recalibrate drive
29FD_CSENSE= 008H ; Sense interrupt status
30FD_CSEEK= 00FH ; Seek to another track
31FD_CREAD= 046H ; MFM read, skip deleted data
32FD_CWRITE= 045H ; MFM write, skip deleted data
33FD_CSPEC= 003H ; Special - step rate, head load/unload
34
35; Status codes
36
37FD_SDIO= 01000000B ; Transfer direction (0 -> controller)
38FD_SRQM= 10000000B ; Controller ready for next data
39
40; Hard disk controller commands
41HD_CSENS= 03H ; request sense block
42HD_CREAD= 08H ; read
43HD_CWRITE= 0AH ; write
44
45HDcontrolbyte= 05H ; step rate = 70 us.
46
47; I/O ports
48
49FD_PSEL= 03F2H ; Controls drive select and motors
50FD_PDAT= 03F5H ; Data transfer to/from controller
51FD_PSTAT= 03F4H ; Controller status
52FD_PCMD= 03F7H ; Controller command register
53
54HD_PDAT= 0320H ; read/write data
55HD_PSTAT= 0321H ; controller status
56HD_PSEL= 0322H ; controller select
57HD_PMSK= 0323H ; DMA and interrupt mask bits
58
59PDMA= 0 ; Base of ports for DMA control
60PDMAX= 7FH ; Address extension regs for DMA
61 ;NOTE base address suitable for ch. 2 & 3 only
62FD_DMA= 2 ; floppy disk DMA channel
63HD_DMA= 3 ; hard disk DMA channel
64
65DMA_READ= 44H ; DMA read command
66DMA_WRITE= 48H ; DMA write command
67
68; Misc
69
70DORmask= 00CH ; Not reset, enable DMA & interrupt
71
72
73
74SUBTTL Data for performing requests
75PAGE +
76
77;* Dos Request Packet structure
78
79DosPacket STRUC
80 RqCmdLen DB 0 ; Length of this command
81 RqUnit DB 0 ; Unit in this driver
82 RqCmd DB 0 ; Command to do
83 RqStatus DW 0 ; Status of request
84 DD 0
85 DD 0 ; Not used
86 RqMedia DB 0 ; Media descriptor
87 RqAddr DW 0 ; Offset of data
88 DW 0 ; Segment of data
89 RqCount DW 0 ; Number of sectors
90 RqFirst DW 0 ; First sector to do
91DosPacket ENDS
92
93; The disk drivers work as a state machine performing the various actions
94; that make up disk I/O.
95
96; Driver states
97; The following states are common to both drivers
98Start= 0 ; Starting I/O
99Calc= 1 ; Calculate position on disk
100Done= 7 ; I/O is done
101Idle= 8 ; Drive is inactive
102Error= 9 ; Have an error
103; The following states are used by the floppy driver only
104Select= 2 ; Select drive, start motor, seek
105Recal= 3 ; Drive was just recalibrated
106Seek= 4 ; Seek just finished
107Settle= 5 ; Head has settled
108RdWri= 6 ; Read/write is done
109; The following states are used by the fixed driver only
110Verify= 6 ; Start verify portion of write
111
112
113DeviceStruc STRUC
114 State DW Idle ; Current drive state
115 Current DW -1 ; Current active drive
116 ErrCnt DB 0 ; # of errors in doing request
117 Flags DB 0 ; Various bit flags, see below
118 DOR DB 0 ; Copy of select/motor reg
119; Following values are set by Setup from the request packet and are
120; updated after each transfer is completed.
121 Unit DB 0 ; Unit
122 First DW 0 ; 1st sector of request
123 RealAddr DD 0 ; Real addr of data when Addr is
124 ; scratch buffer.
125 Count DW 0 ; Number of sectors to xfer
126; Following values are set by MapSector.
127 Cyl DW 0 ; Cylinder
128 Sector DB 0 ; Sector - zero based
129 Head DB 0 ; Head
130 NumSectors DW 0 ; Number of sectors to do
131 NumBytes DW 0 ; Number of bytes
132 Addr DD 0 ; Pointer to data buffer
133; Device dependent data
134 ST0 DB 0 ; floppy controller ST0
135 ST1 DB 0 ; floppy controller ST1
136 ST2 DB 0 ; floppy controller ST2
137 CHRN DB 0,0,0,0 ; other floppy status returns
138DeviceStruc ENDS
139 DCB EQU ST0 ; Fixed disk Device Control Block
140
141; Bits in Flags
142
143 Factive= 1 ; Actively working on something
144 F2step= 2 ; Must double step when seeking
145 Fwrite= 4 ; This is a write, not a read
146 Fverify= 8 ; This is a verify, not a rd/wr
147 Fwrap1= 010H ; We are currently using ScratchBuffer
148 Fwrap2= 020H ; We have used ScratchBuffer in this req
149
150BiosSeg GROUP Code,BiosInit
151
152Code SEGMENT BYTE PUBLIC 'CODE'
153 ASSUME CS:BiosSeg
154
155IFDEF DEBUGFLG
156 EXTRN BUGBITS:BYTE,DPRINTF:NEAR
157ENDIF
158
159SUBTTL Device data
160PAGE +
161
162Floppy DeviceStruc <>
163Fixed DeviceStruc <>
164
165;* Per drive information, including BPBs
166
167DriveStruc STRUC
168 BPBsecsiz DW 512 ; Physical sector size
169 BPBsecpau DB 1 ; Sectors/Allocation unit
170 BPBressec DW 1 ; Reserved sectors for DOS
171 BPBnfat DB 2 ; # of allocation tables
172 BPBndir DW 64 ; # of directory entries
173 BPBnsec DW 9*40 ; Number of sectors
174 BPBmediab DB 0FCH ; Media descriptor
175 BPBnfatsec DW 2 ; # of FAT sectors
176 BPBtrksiz DW 9 ; # of sectors/track
177 BPBnhead DW 1 ; # of heads
178 BPBhidsec DW 0 ; Hidden sector count
179 Timer DB 0 ; Countdown for motor off
180 DrvFlag DB 1 ; Per-drive flags, see below
181 TPI DB 0 ; Drive TPI= Not present, 48, 96
182 CurCyl DW -1 ; Current cylinder
183DriveStruc ENDS
184
185; DrvFlag values
186Frestor= 1 ; restore needed
187Fmotoron= 2 ; motor is on
188
189DriveA DriveStruc <> ; floppy drive 0
190DriveB DriveStruc <> ; floppy drive 1 or 0
191DriveC DriveStruc <> ; hard drive 0 or floppy drive 2
192DriveD DriveStruc <> ; hard drive 1 or floppy drive 3
193
194FDinfo DW DriveA
195 DW DriveB
196HDinfo DW DriveC
197 DW DriveD
198
199
200; Structure of parameter block for floppy pointed to by 0:4*1E
201
202FloppyParameter STRUC
203 Spec1 DB 0 ; 0 1st byte for specify cmd
204 Spec2 DB 0 ; 1 2nd byte for specify cmd
205 DelayOff DB 0 ; 2 # of Ticks(1/18.2) until
206 ; motor shut off
207 SectorSize DB 0 ; 3 Sector size(128,256,512,1024)
208 ; = (O,1,2,3 are put here)
209 CylSize DB 0 ; 4 Number of sectors/cylinder
210 DataGap DB 0 ; 5 Gap length of read/write
211 ValueDTL DB 0 ; 6 Data length (ignored)
212 FormatGap DB 0 ; 7 Gap for format operation
213 FormatFill DB 0 ; 8 Fill char for format
214 DelaySettle DB 0 ; 9 Head settle time in msec
215 DelayMotor DB 0 ; 10 Motor start time in 1/8 sec
216FloppyParameter ENDS
217
218
219ScratchBuffer DB 512 DUP(?) ; Scratch buffer for when DMA fails
220 ; Hope we don't handle >512 sector
221 ; size
222
223;* Miscellaneous data
224
225Single DB 0 ; non-zero if 1 floppy disk system
226 ; in this case, NumFloppy will be 2
227
228SUBTTL Data for interface to 4.0
229PAGE +
230
231 EXTRN DosFunction:DWORD ; Addr of DOS function routine
232
233; Dos helper functions used by disk driver
234
235 PullRequest = 2 ; Pull a request from the queue
236 PushRequest = 4 ; Add a request to the queue
237 BlockProcess = 9 ; Block process until I/O done
238 ContinueProcess = 10 ; I/O done, continue process
239
240int_savregs= 32H ; interrupt routine which saves all regs
241
242
243SwapSem1 DB 0 ; non-zero if waiting to swap disks
244SwapSem2 DB 0 ; non-zero if waiting to prompt for swap
245ScratchBufSem DB 0 ; semaphore controlling ScratchBuffer
246
247SEM_WANT= 2
248SEM_BUSY= 1
249
250SemWait Macro wchan
251local l1,l2
252 pushf
253l1: cli
254 test wchan,SEM_BUSY ;;semaphore busy?
255 jz l2 ;;no
256 or wchan,SEM_WANT ;;say we want it
257 mov ax,cs
258 mov bx,OFFSET wchan
259 xor cx,cx
260 mov dx,BlockProcess
261 call [DosFunction] ;;wait till semaphore released
262 jmp l1
263l2: or wchan,SEM_BUSY ;;claim semaphore
264 popf
265 endm
266
267SemSig Macro wchan
268local l
269 test wchan,SEM_WANT ;;anyone waiting on semaphore?
270 jz l
271 mov ax,cs
272 mov bx,OFFSET wchan
273 mov dx,ContinueProcess
274 call [DosFunction]
275l: and wchan,NOT (SEM_WANT+SEM_BUSY)
276 endm
277
278
279FloppyQueue DD 0 ; List of requests for floppy
280FixedQueue DD 0 ; List of requests for fixed disk
281
282; Device driver headers
283
284 PUBLIC FloppyDevice
285FloppyDevice LABEL WORD
286 DD FixedDevice ; Next device is hard disk
287 DW 100000B ; This is 4.0 driver
288 DW JustReturn ; Strategy does nothing
289 DW FloppyRequest ; Interrupt does the work
290NumFloppy DB 4 ; Handle 4 floppys maximum
291 DB 0 ; can be addressed as word also
292
293 EXTRN Com1Dev:NEAR
294
295FixedDevice LABEL WORD
296 DD Com1Dev ; Next device is comm port 1
297 DW 100000B ; This is 4.0 driver
298 DW JustReturn ; Strategy does nothing
299 DW FixedRequest ; Interrupt does work (misnomer)
300NumFixed DB 0 ; Handle 2 hard disks maximum
301
302
303; Utility routines which reside in the BIOS main module
304
305 EXTRN Interrupt:NEAR ; BIOS interrupt routine(misnomer)
306 EXTRN CmdErr:NEAR
307 EXTRN StatusDevReady:NEAR
308 EXTRN StatusComplete:NEAR
309 EXTRN StatusError:NEAR
310 EXTRN SetStatus:NEAR
311
312JustReturn PROC FAR
313 RET
314JustReturn ENDP
315
316FloppyRequest PROC FAR
317 debug 4,2,<FloppyRequest, es:bx $x:$x, cmd $d\n>,<es,bx,<word ptr es:[bx.RqCmd]>>
318 PUSH SI
319 LEA SI,FloppyFunction ; 4.0 function routines
320 JMP Interrupt ; Let BIOS figure out what to do
321FloppyRequest ENDP
322
323; Dispatch table for actions of the floppy requested by 4.0
324
325FloppyFunction LABEL WORD
326 DW FloppyInit ; 0 Initialize
327 DW FloppyCheck ; 1 Check media
328 DW FloppyBuild ; 2 Build BPB
329 DW CmdErr ; 3 IOCTL input
330 DW FloppyRead ; 4 Read
331 DW StatusDevReady ; 5 Non-destructive read
332 DW StatusComplete ; 6 Input status
333 DW StatusComplete ; 7 Input flush
334 DW FloppyWrite ; 8 Write
335 DW FloppyWriteV ; 9 Write with verify
336 DW CmdErr ; 10 Output status
337 DW CmdErr ; 11 Output flush
338 DW CmdErr ; 12 IOCTL output
339 DW CmdErr ; 13 Device open
340 DW CmdErr ; 14 Device close
341 DW CmdErr ; 15 Removable media
342 DW CmdErr ; 16 Generic IOCTL request
343
344FixedRequest PROC FAR
345 debug 8,2,<FixedRequest, es:bx $x:$x, cmd $d\n>,<es,bx,<word ptr es:[bx.RqCmd]>>
346 PUSH SI
347 LEA SI,FixedFunction ; 4.0 function routines
348 JMP Interrupt ; Let BIOS figure out what to do
349FixedRequest ENDP
350
351; Dispatch table for actions of the hard disk requested by 4.0
352
353FixedFunction LABEL WORD
354 DW FixedInit ; 0 Initialize
355 DW FixedCheck ; 1 Check media
356 DW FixedBuild ; 2 Build BPB
357 DW CmdErr ; 3 IOCTL input
358 DW FixedRead ; 4 Read
359 DW StatusDevReady ; 5 Non-destructive read
360 DW StatusComplete ; 6 Input status
361 DW StatusComplete ; 7 Input flush
362 DW FixedWrite ; 8 Write
363 DW FixedWriteV ; 9 Write with verify
364 DW CmdErr ; 10 Output status
365 DW CmdErr ; 11 Output flush
366 DW CmdErr ; 12 IOCTL output
367 DW CmdErr ; 13 Device open
368 DW CmdErr ; 14 Device close
369 DW CmdErr ; 15 Removable media
370 DW CmdErr ; 16 Generic IOCTL request
371
372
373SUBTTL Data for routines that make direct Int 13 requests
374PAGE +
375
376
377RealInt13Vec dw 0 ; Used to make Int 13 requests
378 dw 0
379OldIntDVec dw 0 ; Must be reset when Int 13's on hard
380 dw 0 ; disk.
381OldIntEVec dw 0 ; Must be reset when Int 13's on floppy
382 dw 0 ; disk.
383SemDiskIO db 0 ; Semaphore controlling disk io
384SemInt13 db 0 ; Semaphore controlling Int 13's
385
386
387SUBTTL 4.0 device driver routines (system entry points)
388PAGE +
389
390BiosInit SEGMENT PARA PUBLIC 'CODE'
391 ASSUME CS:BiosSeg
392
393 PUBLIC Disk_Init
394Disk_Init PROC
395;**************************************************************
396; This routine performs device dependent initialization
397; during the BIOS initialization. Not to be confused
398; with the device initialization entry points which are
399; called later on and perform different functions.
400;
401; AFTER THE EQUIPMENT CALL (INT 11H) BITS 6&7 WILL TELL
402; THE NUMBER OF FLOPPY DISKS IN THE SYSTEM.
403; THE INDICATIONS ARE AS FOLLOWS:
404;
405; BITS 7 6 DRIVES
406; 0 0 1
407; 0 1 2
408; 1 0 3
409; 1 1 4
410;**************************************************************
411
412 debug 12,1,<Performing disk driver pre-DOS initialization\n>,<>
413 PUSH CS
414 POP DS
415
416 ASSUME DS:BiosSeg
417 INT 11H ;GET EQUIPMENT STATUS
418 rol al,1 ; rotate around to low order bits
419 rol al,1
420 AND AL,11B ;MASK DRIVE BITS
421 JNZ NOTSNGL ;Zero means single drive system
422 INC [SINGLE] ;REMEMBER THIS
423 inc al ; make it look like two-drive system
424NOTSNGL:
425 inc al
426 MOV [NumFloppy],AL ;Remember how many drives
427 MOV AH,8
428 MOV DL,80H
429 INT 13H ;Request number of hardfiles attached
430 JC ENDDRV ;Carry indicates old rom, so no hardfile
431 MOV [NumFixed],DL
432 test dl,dl ; any specified?
433 jz ENDDRV ; no
434 cmp NumFloppy,2 ; too many floppies?
435 jbe ENDDRV
436 mov NumFloppy,2 ; limit to two floppies max.
437ENDDRV:
438
439;* Initialize the hard disk BPBs
440
441 MOV DL,80H
442 MOV DI,OFFSET DriveC
443 CMP [NumFixed],0
444 JLE ITSOK
445 CALL SETHRD ;SET UP FIRST HARDFILE
446
447 MOV DL,81H ;SET UP FOR NEXT CALL
448 MOV DI,OFFSET DriveD
449 JC NOTOK
450 CMP [NumFixed],2
451 JZ SETIT
452 JMP SHORT ITSOK
453NOTOK:
454 MOV DI,OFFSET DriveC
455 DEC [NumFixed]
456 CMP [NumFixed],0
457 JZ ITSOK
458SETIT: CALL SETHRD ;SET UP SECOND HARDFILE
459 JNC ITSOK
460 DEC [NumFixed]
461ITSOK:
462 cmp [NumFixed],0 ; any hard disks found?
463 jnz itsok2 ; yes
464 mov ax,[FixedDevice] ; no, patch device chain to skip fixed disk
465 mov [FloppyDevice],ax
466itsok2:
467 push es ; Install Int 13 handler and save the
468 xor ax,ax ; old value of the interrupt vector.
469 mov es,ax
470 mov ax,es:[4*13h]
471 mov [RealInt13Vec],ax
472 mov ax,OFFSET Int13Handler
473 mov es:[4*13H],ax
474 mov ax,es:[4*13h+2]
475 mov [RealInt13Vec+2],ax
476 mov es:[4*13H+2],cs
477 mov ax,es:[4*0dh] ; Save original Int D vector
478 mov [OldIntDVec],ax
479 mov ax,es:[4*0dh+2]
480 mov [OldIntDVec+2],ax
481 mov ax,es:[4*0eh] ; Save original Int E vector
482 mov [OldIntEVec],ax
483 mov ax,es:[4*0eh+2]
484 mov [OldIntEVec+2],ax
485 pop es
486 ret
487Disk_Init ENDP
488
489;
490; READ A BOOT RECORD INTO Scratch buffer
491;
492GETBOOT:
493 MOV CX,1
494 MOV AX,0201H
495 push CS
496 pop es
497 mov BX,OFFSET ScratchBuffer
498 xor DH,DH
499 INT 13H
500 JC SETRET
501 CMP WORD PTR ES:[BX+1FEH],0AA55H
502 JNZ SETRET
503 RET
504;
505; SETUP VARIABLE SIZED HARDFILE
506; ON ENTRY DL=DRIVE NUMBER (80 OR 81)
507; DI=PTR TO B.P.B
508;
509SETHRD: PUSH DX
510 MOV AH,8 ;GET DRIVE PARAMETERS
511 INT 13H
512 INC DH
513 MOV BYTE PTR [DI].BPBnhead,DH
514 POP DX
515 JC SETRET
516 AND CL,3FH
517 MOV BYTE PTR [DI].BPBtrksiz,CL
518 CALL GETBOOT ;GET THE BOOT RECORD
519 JC SETRET
520 add BX,1C2H
521 mov cx,4
522SET1: CMP BYTE PTR ES:[BX],1
523 JZ SET2
524 ADD BX,16
525 loop SET1
526SETRET: STC ;NOT FOUND SO USE DEFAULTS
527 debug 8,3,<Sethrd err rtn: drive $x stat $x\n>,<dx,ax>
528 RET
529
530SET2: MOV AX,ES:[BX+4]
531 MOV DS:[DI].BPBhidsec,AX ;SET HIDDEN SECTOR COUNT
532 MOV AX,ES:[BX+8]
533 CMP AX,64 ;HAS TO BE AT LEAST 32K
534 JB SETRET
535 MOV DS:[DI].BPBnsec,AX ;SAVE LOGICAL SECTOR COUNT
536 MOV CX,0100H ;SET CLUS SIZE AND SHIFT COUNT
537 MOV DX,64 ;SET NUMBER OF DIR ENTRIES
538 CMP AX,512
539 JBE SET3
540
541 ADD CH,CH
542 INC CL
543 MOV DX,112
544 CMP AX,2048
545 JBE SET3
546
547 ADD CH,CH
548 INC CL
549 MOV DX,256
550 CMP AX,8192
551 JBE SET3
552
553 ADD CH,CH
554 INC CL
555 ADD DX,DX
556 CMP AX,32680 ;NOT 32768! MAX NUMBER OF CLUSTERS=4085
557 JBE SET3
558
559 ADD CH,CH
560 INC CL
561 ADD DX,DX
562SET3:
563;
564; DX=NUMBER OF DIR ENTRIES, CH=NUMBER OF SECTORS PER CLUSTER
565; CL=LOG BASE 2 OF CH
566;
567; NOW CALCULATE SIZE OF FAT TABLE
568;
569 MOV [DI].BPBndir,DX ;SAVE NUMBER OF DIR ENTRIES
570 MOV [DI].BPBsecpau,CH ;SAVE SECTORS PER CLUSTER
571 XOR BX,BX
572 MOV BL,CH
573 DEC BX
574 ADD BX,AX
575 SHR BX,CL ;DIVIDE BY SECTORS/CLUSTER
576 INC BX
577 AND BL,11111110B ;MAKE SURE COUNT IS EVEN
578 MOV SI,BX
579 SHR BX,1
580 ADD BX,SI ;MULTIPY BY 1.5
581 ADD BX,511
582 SHR BH,1
583 MOV BYTE PTR [DI].BPBnfatsec,BH ;SAVE NUMBER OF FAT SECTORS
584 MOV [DI].BPBmediab,0F8H ; set media byte
585 CLC
586 RET
587BiosInit ENDS
588
589 ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING
590
591FloppyInit PROC
592 debug 4,3,<Diskette initialization>,<>
593 push ds ; install floppy interrupt routine
594 xor ax,ax
595 mov ds,ax
596 mov ax,OFFSET FloppyInterrupt
597 mov ds:[4*0eH],ax
598 mov ds:[4*0eH+2],cs
599 pop ds
600 call Rst765
601 mov ah,[NumFloppy]
602 mov di,OFFSET FDinfo
603DBBEG 4,3
604 jmp SHORT iniret
605DBEND
606 jmp bpbret
607ELSE
608 jmp SHORT bpbret
609ENDIF
610FloppyInit ENDP
611
612FixedInit PROC
613 debug 8,3,<Hard disk initialization>,<>
614 push ds ; install fixed disk interrupt routine
615 xor ax,ax
616 mov ds,ax
617 mov ax,OFFSET FixedInterrupt
618 mov ds:[4*0dH],ax
619 mov ds:[4*0dH+2],cs
620 pop ds
621 in al,21H ; unmask fixed disk interrupts
622 and al,0DFH
623 out 21H,al
624 mov dx,HD_PMSK ; set interrupt and DMA mask bits
625 mov al,3
626 out dx,al
627 mov ah,[NumFixed]
628 mov di,OFFSET HDinfo
629DBBEG 8,3
630iniret: debug 12,3,< - Num=$x BPB table=$x:$x\n>,<ax,cs,di>
631DBEND
632ENDIF
633 jmp SHORT bpbret
634FixedInit ENDP
635
636FloppyBuild PROC
637 mov ah,byte ptr es:[di]
638 call FDGetBPB
639bpbret: mov [bx.RqMedia],ah
640 mov [bx.RqCount],di
641 mov [bx.RqCount+2],CS
642 jmp StatusComplete
643FloppyBuild ENDP
644
645FixedBuild PROC
646 mov ah,byte ptr es:[di]
647 call HDGetBPB
648 jmp SHORT bpbret
649FixedBuild ENDP
650
651;*** FloppyCheck - check to see if the disk may have been changed.
652;
653; ENTRY AL = unit #
654; AH = media byte
655; EXIT Return value in request header set to one of:
656; 1 Media may have been changed
657; 0 Media not changed
658; -1 Media was probably changed
659;
660
661FloppyCheck PROC
662 MOV DL,1 ; Assume not changed
663 cmp AH,0f8H ; Is disk removable?
664 JE FloppyCheckDone ; No, can't be changed then
665 cmp Single,0 ; single drive system?
666 je flchk1 ; no, check drive state
667 cmp Floppy.Unit,al ; unit = current drive?
668 je flchk1 ; yes, check drive state
669 mov DL,-1 ; say media changed for sure
670 jmp FloppyCheckDone
671flchk1: MOV CX,AX
672 XOR CH,CH
673 MOV SI,CX
674 ADD SI,SI
675 MOV SI,FDinfo[SI] ; Get pointer to drive info
676 TEST CS:[SI].DrvFlag,Fmotoron ; Is motor on?
677 JNZ FloppyCheckDone ; Yes, media not changed then
678 XOR DL,DL ; No, might have been changed
679FloppyCheckDone:
680 MOV BYTE PTR DS:[BX].RqAddr,DL
681 JMP StatusComplete ; Return whether media changed
682FloppyCheck ENDP
683
684
685FixedCheck PROC
686 MOV DL,1
687 JMP FloppyCheckDone
688FixedCheck ENDP
689;*** FloppyRead, FloppyWrite, FloppyWriteV - Basic I/O entry points
690;
691; FloppyRead, FloppyWrite and FloppyWriteV are the basic I/O
692; routines used by the DOS. They really do not do much except
693; queue the request and start the device if it is idle.
694; For single drive floppy systems, they also handle the
695; switching of disks when I/O changes from A to B or vice-versa.
696;
697; ENTRY DS:BX Packet address
698; ES:DI Transfer address
699; AL Unit #
700; AH Media Byte
701; CX # of sectors
702; DX Starting sector
703;
704; EXIT DS:BX Packet Addr
705; CX # of sectors left to do
706;
707; USES SI
708
709FloppyRead LABEL NEAR
710FloppyWrite LABEL NEAR
711FloppyWriteV PROC
712 debug 4,2,<Fl rd/wt/ver Req $x:$x unit $b sec $d nsec $d\n>,<ds,bx,ax,dx,cx>
713 call BlockIfLocked
714 push di
715 call FDGetBPB ; cs:di => BPB
716 mov si,dx
717 add si,cx ; compute last sector + 1
718 cmp si,cs:[di.BPBnsec]
719 mov si,di
720 pop di
721 jbe flrw1
722 mov al,8 ; ERROR - Sector not found
723 jmp StatusError
724
725flrw1: OR CX,CX ; Anything to do?
726 JNZ flrw2 ; Yes
727 JMP StatusComplete ; No, all done now
728flrw2:
729 CMP Single,0 ; Is this a single drive system?
730 JE flrw3 ; No, don't check for drive change
731 CALL FloppyChange ; See if should change disks
732flrw3:
733 call CheckWrap
734 push ds
735 pop es ; ES:BX = Request addr
736 push cs
737 pop ds
738 LEA SI,FloppyQueue ; DS:SI = ptr to head of queue
739 MOV DX,PushRequest
740 CALL DosFunction ; Add request to list
741 push es
742 pop ds ; Back to DS:BX is request
743 pushf
744 cli ; interrupts off while testing state
745 TEST Floppy.Flags,Factive ; Is driver active?
746 JNE FloppyActive ; Yes, driver will get to it
747 PUSH DS
748 PUSH BX ; Save some regs
749 OR Floppy.Flags,Factive
750 MOV Floppy.State,Start ; Want to start I/O
751 CALL FloppyExecute ; Start up the driver
752 POP BX
753 POP DS ; Restore regs
754flrw4: test DS:[BX].RqStatus,0100H ; IO completed?
755 JNZ FloppyIOdone ; yes
756
757FloppyActive:
758 MOV AX,DS ; AX:BX = request
759 xor cx,cx
760 push bx
761 MOV DX,BlockProcess
762 CALL DosFunction ; Block until I/O is done
763 pop bx
764 jmp flrw4 ; test completion status again
765FloppyIOdone:
766 popf
767 MOV AX,DS:[BX].RqStatus ; Need AX = status
768 MOV CX,DS:[BX].RqCount ; Need CX = count left to do
769 debug 4,2,<Fl rd/wt/ver DONE Req $x:$x stat $x resid $d\n>,<ds,bx,ax,cx>
770 JMP SetStatus ; Return to DOS with results
771FloppyWriteV ENDP
772
773
774FixedRead LABEL NEAR
775FixedWrite LABEL NEAR
776FixedWriteV PROC
777 debug 8,2,<Fix rd/wt/ver Req $x:$x unit $b sec $d nsec $d\n>,<ds,bx,ax,dx,cx>
778 call BlockIfLocked
779 push di
780 call HDGetBPB ; cs:di => BPB
781 mov si,dx
782 add si,cx ; compute last sector + 1
783 cmp si,cs:[di.BPBnsec]
784 mov si,di
785 pop di
786 jbe fxrw1
787 mov al,8 ; ERROR - Sector not found
788 jmp StatusError
789
790fxrw1: OR CX,CX ; Anything to do?
791 JNZ fxrw2 ; Yes
792 JMP StatusComplete ; No, all done now
793fxrw2:
794 call CheckWrap
795 push ds
796 pop es ; ES:BX = Request addr
797 push cs
798 pop ds
799 LEA SI,FixedQueue ; DS:SI = ptr to head of queue
800 MOV DX,PushRequest
801 CALL DosFunction ; Add request to list
802 push es
803 pop ds ; Back to DS:BX is request
804 pushf
805 cli ; interrupts off while testing state
806 TEST Fixed.Flags,Factive ; Is driver active?
807 JNE FixedActive ; Yes, driver will get to it
808 PUSH DS
809 PUSH BX ; Save some regs
810 OR Fixed.Flags,Factive
811 MOV Fixed.State,Start ; Want to start I/O
812 CALL FixedExecute ; Start up the driver
813 POP BX
814 POP DS ; Restore regs
815fxrw4: test DS:[BX].RqStatus,0100H ; IO completed?
816 JNZ FixedIOdone ; yes
817
818FixedActive:
819 MOV AX,DS ; AX:BX = request
820 xor cx,cx
821 push bx
822 MOV DX,BlockProcess
823 CALL DosFunction ; Block until I/O is done
824 pop bx
825 jmp fxrw4 ; test completion status again
826FixedIOdone:
827 popf
828 MOV AX,DS:[BX].RqStatus ; Need AX = status
829 MOV CX,DS:[BX].RqCount ; Need CX = count left to do
830 debug 8,2,<Fx rd/wt/ver DONE Req $x:$x stat $x resid $d\n>,<ds,bx,ax,cx>
831 JMP SetStatus ; Return to DOS with results
832FixedWriteV ENDP
833
834;*** CheckWrap - check whether a request crosses a 64Kb boundary
835;
836; CheckWrap will check whether the request given in DS:BX
837; crosses a 64Kb boundary. A portion of such requests must
838; be done using ScratchBuffer for a single sector transfer.
839; This routine ensures that only one such request is put into
840; either of the request queues at any time.
841;
842; ENTRY DS:BX Request header
843; ES:DI Transfer address
844; CS:SI Pointer to BPB
845; CX Sector count
846; EXIT When it's safe to proceed.
847; USES AX,BP
848
849CheckWrap PROC
850 push dx
851 push cx
852 mov ax,cx
853 mul cs:[si.BPBsecsiz]
854 mov dx,es ; compute offset
855 mov cl,4
856 shl dx,cl
857 add dx,di
858 clc ; now see if offset+nbytes overflows
859 add dx,ax
860 jnc chkw8
861 debug 12,10h,<CheckWrap $x $x:$x >,<ax,es,di>
862 push bx
863 SemWait ScratchBufSem ; wait for ScratchBuffer to be available
864 pop bx
865
866chkw8: pop cx
867 pop dx
868 ret
869CheckWrap ENDP
870
871
872;*** FloppyChange - check whether floppy disk must be changed
873;
874; FloppyChange is called on a single drive system to simulate a
875; two drive system. The current request for I/O is checked against
876; what the driver considers to be the current drive. If they are
877; the same, FloppyChange just returns. Otherwise, SwapSem2 is set
878; and the current process is blocked on SwapSem2. Any process that
879; attempts I/O while SwapSem2 is set is blocked on SwapSem1. When
880; SwapSem2 is cleared, these processes are continued. When the
881; driver becomes idle and SwapSem2 is set, the Idle state continues
882; the blocked process. This process then puts out the message about
883; switching disks and waits for a user reply. When it is given,
884; FloppyChange clears SwapSem1 and causes the I/O to be started.
885;
886; ENTRY DS:BX Pointer to I/O request
887;
888; USES AX,DX
889;
890
891
892FloppyChange PROC
893 push cx
894 pushf
895 push bx
896 SemWait SwapSem1 ; Currently waiting to switch disk?
897 pop bx
898
899flcha1: and SwapSem1,NOT SEM_BUSY ; reset BUSY for now
900 MOV AL,DS:[BX].RqUnit ; Get desired unit
901 CMP AL,Floppy.Unit ; Switching A and B drive?
902 JE flcha7 ; No, keep using this drive
903 CLI ; ** Disable interrupts
904 OR SwapSem1,SEM_BUSY ; Flag waiting to switch
905 test Floppy.Flags,Factive ; Is driver idle?
906 JE flcha2 ; Yes, don't need to wait
907 push bx
908 SemWait SwapSem2
909 pop bx
910 jmp flcha1
911flcha2:
912 popf ; restore interrupt state
913 pushf
914 ADD AL,"A" ; Convert to drive letter
915 MOV CS:DriveLetter,AL ; Set the letter
916 PUSH DS
917 PUSH SI
918 push bx
919 push cs
920 pop ds
921 LEA SI,SwitchMsg
922flcha4:
923 LODSB
924 OR AL,AL ; End of message?
925 JZ flcha5 ; Yes
926 INT 29H ; No, output char
927 JMP flcha4 ; Put out whole msg
928
929flcha5:
930 mov ah,1 ; Flush keyboard input
931 int 16H
932 jz flcha5
933 XOR AH,AH
934 INT 16H ; Wait for a char
935 pop bx
936 POP SI
937 POP DS
938flcha7:
939 push bx
940 SemSig SwapSem1 ; Allow blocked processes to continue
941 pop bx
942flcha8:
943 popf
944 pop cx
945 RET
946
947FloppyChange ENDP
948
949
950SwitchMsg LABEL WORD
951 DB 13,10,"Insert diskette for drive "
952DriveLetter LABEL BYTE
953 DB "A: and strike",13,10,"any key when ready",13,10,10,0
954
955
956Int13Handler Proc Far
957 push dx ; Save regs used in local processing
958 push cx
959 push bx
960 push ax
961 pushf
962LockCheck:
963 cli ; If any Int 13 request is already
964 cmp SemInt13,0 ; pending, block this process until
965 jz NotLocked ; the previous one finishes.
966 mov ax,cs
967 mov bx,offset SemInt13
968 xor cx,cx
969 mov dx,BlockProcess
970 call DosFunction
971 jmp LockCheck
972NotLocked:
973 mov SemInt13,1 ; Lock out other disk requests
974 popf
975 pushf
976BusyCheck:
977 cli
978 cmp SemDiskIO,0 ; If the disks are busy, block this
979 jz DiskFree ; process till they free up.
980 mov ax,cs
981 mov bx,offset SemDiskIO
982 xor cx,cx
983 mov dx,BlockProcess
984 call DosFunction
985 jmp BusyCheck
986DiskFree:
987 popf
988 sti
989 pop ax ; Restore regs for call
990 pop bx
991 pop cx
992 pop dx
993 push dx
994 push cx
995 push bx
996 pushf
997 call dword ptr [RealInt13Vec]
998 mov SemInt13,0
999 push ax
1000 pushf
1001 mov ax,cs ; Unblock anything that is waiting
1002 mov bx,offset SemInt13
1003 mov dx,ContinueProcess
1004 call DosFunction
1005 popf ; Restore user regs
1006 pop ax
1007 pop bx
1008 pop cx
1009 pop dx
1010 ret 2
1011Int13Handler endp
1012
1013
1014SUBTTL Fixed disk startup routine
1015PAGE +
1016
1017; FixedExecute processes a disk request after it has been set up. When the
1018; disk is inactive (State = Idle), it is called to start the device. For all
1019; subsequent events, it is called on the disk interrupt which signaled the
1020; completion of that subfunction. Some states do not involve waiting for an
1021; interrupt to occur. This routine runs entirely off the 'Fixed' data structure
1022
1023FixedDispatch LABEL WORD
1024 DW FxExStart
1025 DW FxExCalc
1026 DW FxExError ;; BUGBUG really error in state machine
1027 DW FxExError ;; BUGBUG really error in state machine
1028 DW FxExError ;; BUGBUG really error in state machine
1029 DW FxExError ;; BUGBUG really error in state machine
1030 DW FxExVerify
1031 DW FxExDone
1032 DW FxExIdle
1033 DW FxExError
1034
1035FixedExecute PROC
1036 push cs ; CS -> DS
1037 pop ds
1038 ASSUME DS:BiosSeg
1039 MOV BX,Fixed.State ; Get current state
1040 debug 8,4,<FxEx state $d >,<bx>
1041 ADD BX,BX
1042 JMP FixedDispatch[BX] ; Dispatch to correct routine
1043
1044
1045;* Fixed state Start
1046;
1047; Do setup calculations to figure out sector, start
1048; up motor, advance to Calc state.
1049;
1050; Entered on initially picking up a new request to do and on error retries.
1051; If error retries start here, then multiple sector requests will always start
1052; at the beginning rather than at the point of the error! Why?
1053
1054FxExStart:
1055 mov si,OFFSET Fixed ; SI = pointer to per-device info.
1056 les bx,FixedQueue ; ES:BX = pointer to current request
1057 mov al,es:[bx].RqUnit
1058 call HDGetBPB ; DI = drive parameters
1059 CALL Setup ; Do setup calculations
1060 MOV Fixed.State,Calc ; Advance to next state
1061 JMP FixedExecute ; Now return to do Calc code
1062
1063
1064
1065;* Fixed state Calc
1066;
1067; Calculate cylinder, head and sector, wait for motor
1068; start or head load, advance to Select state.
1069;
1070; Entered after Start state and also on further sectors of a multiple sector
1071; request.
1072
1073FxExCalc:
1074 mov si,OFFSET Fixed ; SI = pointer to per-device info.
1075 les bx,FixedQueue ; ES:BX = pointer to current request
1076 mov al,es:[bx].RqUnit
1077 call HDGetBPB ; DI = drive parameters
1078 CALL MapSector ; Get head, cylinder and sector
1079 test Fixed.Flags,Fwrite
1080 jnz fxxc1
1081 mov al,DMA_read
1082 mov Fixed.DCB,HD_CREAD
1083 jmp SHORT fxxc2
1084fxxc1: mov al,DMA_write
1085 mov Fixed.DCB,HD_CWRITE
1086fxxc2: mov ah,HD_DMA
1087 call DMAsetup ; set up DMA transfer
1088 mov al,Fixed.Unit
1089 mov cl,5
1090 shl ax,cl
1091 or al,Fixed.Head
1092 mov Fixed.DCB+1,al ; set head/unit
1093 mov ax,Fixed.cyl
1094 mov Fixed.DCB+3,al ; set low cylinder
1095 shr ax,1
1096 shr ax,1
1097 and al,0C0H
1098 or al,Fixed.Sector
1099 mov Fixed.DCB+2,al ; set high cylinder/sector
1100 mov al,BYTE PTR Fixed.Numsectors
1101 mov Fixed.DCB+4,al ; set sector count
1102 mov Fixed.DCB+5,HDcontrolbyte ;BUGBUG - what do we want here?
1103 mov al,3
1104 call HDCommand
1105 mov al,Done ; assume next state is Done
1106 test Fixed.Flags,Fverify
1107 jz fxxc3
1108 mov al,Verify
1109fxxc3: mov BYTE PTR Fixed.State,al ; set next state
1110 ret
1111
1112
1113;* Fixed state Verify
1114;
1115; Have executed a write function, must now verify.
1116; BUGBUG For now just go to done state.
1117
1118FxExVerify:
1119 mov Fixed.State,Done
1120 jmp FixedExecute
1121
1122
1123
1124;* Fixed state Done
1125;
1126; If whole request is now complete, mark the request
1127; as done and then start the next one if there is one. If the request is not
1128; yet done, adjust values to show the amount of the request done and then go
1129; back to the Calc state to do next part.
1130
1131FxExDone:
1132 MOV AL,Fixed.Flags
1133 AND AL,Fwrite+Fwrap1 ; Only interested in these bits
1134 CMP AL,Fwrap1 ; Just read into scratch?
1135 JNE fxxd1 ; No
1136 PUSH DS
1137 PUSH ES
1138 MOV CX,Fixed.NumBytes ; CS = # bytes to write from scr
1139 LES DI,Fixed.RealAddr ; ES:DI = real buffer
1140 LDS SI,Fixed.Addr ; DS:SI = scratch buffer
1141 CLD
1142 REP MOVSB ; Copy into real buffer
1143 POP ES
1144 POP DS
1145fxxd1:
1146 MOV AX,Fixed.NumSectors ; AX = # of sectors we did
1147 SUB Fixed.Count,AX ; Adjust count to number left
1148 JZ fxxd3 ; Request is done, tell DOS
1149 ADD Fixed.First,AX ; Advance sector number
1150 MOV AX,Fixed.NumBytes ; Number of bytes handled
1151 ADD WORD PTR Fixed.RealAddr,AX ; Advance data address
1152 MOV Fixed.State,Calc ; Go to Calc state
1153fxexj4: JMP FixedExecute
1154
1155fxxd3:
1156 mov DI,OFFSET Fixed
1157 mov SI,OFFSET FixedQueue ; DS:SI = head of queue
1158 call DoneRequest
1159 JMP fxexj4
1160
1161
1162;* Fixed state Idle
1163;
1164; Nothing hapenning, become inactive.
1165
1166FxExIdle:
1167 and Fixed.Flags,NOT Factive
1168 RET
1169
1170
1171;* Fixed state Error
1172;
1173; Entered when a non-recoverable error is detected.
1174; A sense block has been requested and put into the
1175; DCB.
1176
1177FxExError:
1178 MOV Fixed.State,Done ; Request is done
1179; Set error bits in request packet
1180 MOV AL,Fixed.DCB ; Get status byte
1181 mov bl,al ; isolate error type as word address
1182 and bx,0030h
1183 mov cl,3
1184 shr bx,cl
1185 mov bx,HDErrType[BX] ; index into error table by type
1186 and ax,0Fh ; get error code
1187 cmp al,ds:[bx] ; outside range of table?
1188 jae fxxe1
1189 add bx,ax
1190 mov ah,ds:[bx+1] ; translate error code
1191 jmp SHORT fxxe2
1192fxxe1:
1193 mov ah,12
1194fxxe2: dbbeg 8,4
1195 mov di,OFFSET Fixed.DCB
1196 debug 8,4,<HD error: sense $b$b$b$b code $x\n>,<<[di]>,<[di+1]>,<[di+2]>,<[di+3]>,ax>
1197 dbend
1198 endif
1199 PUSH ES
1200 LES DI,FixedQueue ; Get ptr to request
1201 MOV AL,ah
1202 MOV AH,10000001B
1203 MOV ES:[DI].RqStatus,AX ; Set error and code
1204 POP ES
1205 JMP fxxd3 ; Advance to Done state
1206FixedExecute ENDP
1207
1208;* Traslation of controller error codes to DOS error codes
1209
1210HDErrType DW HDErrTyp0
1211 DW HDErrTyp1
1212 DW HDErrTyp2
1213 DW HDErrTyp3
1214
1215HDErrTyp0 DB 9, 12, 2, 6,10, 2,12, 6,12, 6
1216HDErrTyp1 DB 10, 4, 4, 8,12, 8, 6,12,12, 4, 6
1217HDErrTyp2 DB 2, 3, 8
1218HDErrTyp3 DB 3, 4, 4, 4
1219
1220 ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING
1221
1222FixedInterrupt PROC FAR
1223 debug 8,8,<FxIntr\n>,<>
1224 cmp word [SemDiskIO],0001h
1225 jnz fxinot13
1226 cmp SemInt13,0 ; If a direct Int13 request is being
1227 jz fxinot13 ; made call the ROM floppy interrupt
1228 cmp SemDiskIO,0 ; routine to handle it.
1229 jnz fxinot13
1230 int int_savregs
1231;; in al,21H ; Mask fixed disk interrupts
1232;; or al,20h
1233;; out 21H,al
1234 pushf
1235 call dword ptr [OldIntDVec]
1236 in al,21H ; Unmask fixed disk interrupts
1237 and al,0DFH
1238 out 21H,al
1239 mov dx,HD_PMSK ; set interrupt and DMA mask bits
1240 mov al,3
1241 out dx,al
1242 iret
1243fxinot13:
1244 TEST Fixed.Flags,Factive ; device active?
1245 JZ fxinret ; no, go away
1246 INT int_savregs ; save registers
1247 mov dx,HD_PDAT
1248 in al,dx ; get status reg.
1249;; mov ah,al
1250;; mov dx,HD_PMSK
1251;; xor al,al
1252;; out dx,al ; turn off intr. and DMA.
1253;; test ah,02h ; error bit set?
1254 test al,02h ; error bit set?
1255 jz fxin4 ; no
1256;* error occurred. see if retry, else get error code.
1257 push cs
1258 pop ds
1259 ASSUME ds:BiosSeg
1260 CMP Fixed.ErrCnt,ErrLim ; Reach error limit?
1261 JAE fxin0 ; Yes, request fails
1262 INC Fixed.ErrCnt ; We are doing another try
1263 MOV Fixed.State,Start ; Restart the request
1264 JMP fxin4
1265fxin0: mov Fixed.DCB,HD_CSENS ; send sense command
1266 xor al,al ; reset intr. & DMA masks
1267 call HDCommand
1268 push cs
1269 pop es
1270 mov di,OFFSET Fixed.DCB
1271 mov cx,5
1272fxin1: call HDWaitReq ; get the sense block back
1273 mov dx,HD_PDAT
1274 in al,dx
1275 stosb
1276 loop fxin1
1277 mov Fixed.State,Error
1278
1279 ASSUME ds:NOTHING
1280fxin4: CALL FixedExecute
1281fxinret: push ax
1282 MOV AL,20H ; send EOI to 8259
1283 OUT 20H,AL
1284 pop ax
1285 IRET
1286FixedInterrupt ENDP
1287
1288SUBTTL Floppy disk startup routine
1289PAGE +
1290
1291; FloppyExecute processes a disk request after it has been set up.
1292; When the disk is inactive (State = Idle), it is called to start
1293; the device. For all subsequent events, it is called on the disk
1294; interrupt which signaled the completion of that subfunction.
1295; Some states do not involve waiting for an interrupt to occur.
1296; This routine runs entirely off the 'Floppy' data structure
1297
1298FloppyDispatch LABEL WORD
1299 DW FlExStart
1300 DW FlExCalc
1301 DW FlExSelect
1302 DW FlExRecal
1303 DW FlExSeek
1304 DW FlExSettle
1305 DW FlExRdWri
1306 DW FlExDone
1307 DW FlExIdle
1308 DW FlExError
1309
1310FloppyExecute PROC
1311 push cs ; CS -> DS
1312 pop ds
1313 ASSUME DS:BiosSeg
1314 MOV BX,Floppy.State ; Get current state
1315 debug 4,4,<FlEx state $d >,<bx>
1316 ADD BX,BX
1317 JMP FloppyDispatch[BX] ; Dispatch to correct routine
1318
1319
1320;* Floppy state Start
1321;
1322; Do setup calculations to figure out sector, start
1323; up motor, advance to Calc state.
1324;
1325; Entered on initially picking up a new request to do and on error retries.
1326; If error retries start here, then multiple sector requests will always start
1327; at the beginning rather than at the point of the error! Why?
1328
1329FlExStart:
1330 mov si,OFFSET Floppy ; SI = pointer to per-device info.
1331 les bx,FloppyQueue ; ES:BX = pointer to current request
1332 mov al,es:[bx].RqUnit
1333 mov ah,es:[bx].RqMedia
1334 call FDGetBPB ; DI = drive parameters
1335 CALL Setup ; Do setup calculations
1336 MOV DX,FD_PCMD
1337 MOV AL,Rate44
1338 OUT DX,AL ; Set step rate
1339 MOV Floppy.State,Calc ; Advance to next state
1340flexj1: JMP FloppyExecute ; Now return to do Calc code
1341
1342
1343
1344;* Floppy state Calc
1345;
1346; Calculate cylinder, head and sector, wait for motor
1347; start or head load, advance to Select state.
1348;
1349; Entered after Start state and also on further sectors of a multiple sector
1350; request.
1351
1352FlExCalc:
1353 mov si,OFFSET Floppy ; SI = pointer to per-device info.
1354 les bx,FloppyQueue ; ES:BX = pointer to current request
1355 mov al,es:[bx].RqUnit
1356 mov ah,es:[bx].RqMedia
1357 call FDGetBPB ; DI = drive parameters
1358 CALL MapSector ; Get head, cylinder and sector
1359 MOV Floppy.State,Select ; Will advance to Select state
1360 CALL Sel765 ; Select the drive and maybe wait
1361 JNC FloppyExecute ; Did select with no waiting
1362 RET ; Have set a timer, get out
1363
1364
1365
1366;* Floppy state Select
1367;
1368; Recalibrate the drive if needed. If Seek is
1369; needed, start it and advance to Seek state. Otherwise advance to Settle
1370; state.
1371
1372FlExSelect:
1373 call GetDrivePtr
1374 OR [BX].DrvFlag,Fmotoron ; we've been selected, so motor is on
1375 TEST [BX].DrvFlag,Frestor ; Is a restore needed?
1376 JE NoRestore ; No
1377 call SetTimer2 ; set a sanity/motor stop timer
1378 MOV Floppy.State,Recal ; Next state will be recalibrate
1379 CALL Rcl765 ; Start the recalibrate
1380 RET ; Done until floppy interrupt arrives
1381
1382NoRestore: ; Start the seek if any
1383 CALL Seek765 ; Start the seek to cylinder
1384 JNC SeekOK ; Already on correct cylinder
1385 MOV Floppy.State,Seek ; Next state is Seek
1386 call GetDrivePtr
1387 call SetTimer2 ; set sanity timer
1388 RET ; Done until interrupt on seek done
1389
1390
1391
1392;* Floppy state Recal
1393;
1394; If error, set state is Error. Else, load drive
1395; specs into controller and advance to Select state.
1396
1397FlExRecal:
1398 CALL Sense765
1399 OR AX,AX ; Error in recal?
1400 JNZ SeekErr ; Yes
1401RecalOK:
1402 CALL Spec765 ; Load drive specs
1403 MOV Floppy.State,Select ; Back to select state now
1404flexj2: JMP flexj1
1405
1406
1407
1408;* Floppy state Seek
1409;
1410; If error, advance to Error state. Otherwise, wait
1411; for head to settle and advance to Settle state.
1412
1413FlExSeek:
1414 CALL Sense765 ; Get status of seek
1415 OR AX,AX ; Any error?
1416 JZ SeekOK ; No
1417SeekErr:
1418 CALL GetDrivePtr
1419 OR [BX].DrvFlag,Frestor ; flag restore needed
1420 MOV Floppy.State,Error ; Yes, next state is Error
1421 or Floppy.ST1,8 ; indicate seek error in an unused bit
1422 JMP flexj2
1423
1424SeekOK:
1425 MOV Floppy.State,Settle ; Next state is Settle
1426 MOV AL,DelaySettle
1427 CALL GetFloppyParam ; Get the settle time in Msecs
1428 xor ah,ah
1429 CALL SetTimer1 ; Set the timer
1430 JNC flexj2
1431 RET
1432
1433
1434
1435;* Floppy state Settle
1436;
1437; Start the read/write request and advance to the RdWri state.
1438
1439FlExSettle:
1440 MOV Floppy.State,RdWri ; Advance to read/write state
1441 CALL RdWr765 ; Start the I/O
1442 call GetDrivePtr
1443 call SetTimer2 ; set sanity timer
1444 RET ; Done until floppy interrupt
1445
1446
1447
1448;* Floppy state RdWri
1449;
1450; If error, next state is Error. Otherwise next state is Done.
1451
1452FlExRdWri:
1453 CALL Fini765 ; Get status of I/O
1454 OR AX,AX ; Any error?
1455 JZ RdWriOK ; No
1456 MOV Floppy.State,Error ; Yes, go to error state
1457 JMP flexj2
1458
1459RdWriOK:
1460 MOV Floppy.State,Done ; I/O is done
1461flexj3: JMP flexj2
1462
1463
1464
1465;* Floppy state Done
1466;
1467; If whole request is now complete, mark the request
1468; as done and then start the next one if there is one. If the request is not
1469; yet done, adjust values to show the amount of the request done and then go
1470; back to the Calc state to do next part.
1471
1472FlExDone:
1473 MOV AL,Floppy.Flags
1474 AND AL,Fwrite+Fverify+Fwrap1 ; Only interested in these bits
1475 CMP AL,Fwrap1 ; Just read into scratch?
1476 JNE DoneNotWrap ; No
1477 PUSH DS
1478 PUSH ES
1479 MOV CX,Floppy.NumBytes ; CS = # bytes to write from scr
1480 LES DI,Floppy.RealAddr ; ES:DI = real buffer
1481 LDS SI,Floppy.Addr ; DS:SI = scratch buffer
1482 CLD
1483 REP MOVSB ; Copy into real buffer
1484 POP ES
1485 POP DS
1486DoneNotWrap:
1487 AND AL,Fwrite+Fverify ; Just want to see these bits
1488 CMP AL,Fwrite+Fverify ; Just do write part of write+verify?
1489 JNE DoneNotWritePart ; No
1490 AND Floppy.Flags,NOT Fwrite ; Yes, do verify next
1491 mov Floppy.State,Settle ; don't need to calc or seek
1492 jmp flexj3
1493
1494DoneNotWritePart:
1495 CMP AL,Fverify ; Just do verify part of write+verify?
1496 JNE DoneNotVerify ; No
1497 OR Floppy.Flags,Fwrite ; Yes, flip write back up for next
1498DoneNotVerify:
1499 MOV AX,Floppy.NumSectors ; AX = # of sectors we did
1500 SUB Floppy.Count,AX ; Adjust count to number left
1501 JZ flxd3 ; Request is done, tell DOS
1502 ADD Floppy.First,AX ; Advance sector number
1503 MOV AX,Floppy.NumBytes ; Number of bytes handled
1504 ADD WORD PTR Floppy.RealAddr,AX ; Advance data address
1505 MOV Floppy.State,Calc ; Go to Calc state
1506flexj4: JMP flexj3
1507
1508flxd3:
1509 mov di,OFFSET Floppy
1510 mov SI,OFFSET FloppyQueue ; DS:SI = head of floppy queue
1511 call DoneRequest
1512 JMP flexj4
1513
1514
1515;* Floppy state Idle
1516;
1517; Nothing hapenning except possible motor off timeout.
1518
1519FlExIdle:
1520 call GetDrivePtr
1521 CALL SetTimer2 ; Set the motor timer
1522 and Floppy.Flags,NOT Factive
1523 SemSig SwapSem2 ; someone waiting to switch drive?
1524 RET
1525
1526
1527;* Floppy state Error
1528;
1529; If error count not exceeded, restore the drive and start
1530; the request over again. Otherwise set error in the packet and
1531; advance to the Done state.
1532
1533FlExError:
1534 CALL Rst765 ; Reset the controller
1535 CMP Floppy.ErrCnt,ErrLim ; Reach error limit?
1536 JAE FloppyFails ; Yes, request fails
1537 INC Floppy.ErrCnt ; We are doing another try
1538 MOV Floppy.State,Start ; Restart the request
1539 JMP flexj4 ; Back to state machine loop
1540
1541FloppyFails:
1542 call GetDrivePtr
1543 OR CS:[BX].DrvFlag,Frestor ; Set drive needs a restore
1544 MOV Floppy.State,Done ; Request is done
1545; Set error bits in request packet
1546 MOV AX, WORD PTR Floppy.ST0 ; Get ST0, ST1
1547 mov BL,2 ; Drive not ready?
1548 test AL,0cH
1549 jne ErrorFound
1550 MOV BL,6 ; Bad seek?
1551 TEST AH,8
1552 JNE ErrorFound
1553 MOV BL,4 ; CRC error?
1554 TEST AH,30H
1555 JNE ErrorFound
1556 MOV BL,8 ; Sector not found?
1557 TEST AH,85H
1558 JNE ErrorFound
1559 MOV BL,0 ; Write protect?
1560 TEST AH,2
1561 JNE ErrorFound
1562 MOV BL,12 ; Catch-all error
1563ErrorFound:
1564 debug 4,4,<FD error: status $x code $b\n>,<ax,bx>
1565 PUSH ES
1566 LES DI,FloppyQueue ; Get ptr to request
1567 MOV AL,BL
1568 MOV AH,10000001B
1569 MOV ES:[DI].RqStatus,AX ; Set error and code
1570 POP ES
1571 JMP flxd3 ; Advance to Done state (via shortcut)
1572
1573FloppyExecute ENDP
1574
1575
1576 ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING
1577
1578FloppyInterrupt PROC FAR
1579 debug 4,8,<FlIntr\n>,<>
1580 cmp SemInt13,0 ; If a direct Int13 request is being
1581 jz flinot13 ; made call the ROM floppy interrupt
1582 cmp SemDiskIO,0 ; routine to handle it.
1583 jnz flinot13
1584 int int_savregs
1585 pushf
1586 call dword ptr [OldIntEVec]
1587 iret
1588flinot13:
1589 TEST Floppy.Flags,Factive ; device active?
1590 JZ flinret ; no, go away
1591 INT int_savregs ; save registers
1592 CALL FloppyExecute
1593flinret: push ax
1594 MOV AL,20H ; send EOI to 8259
1595 OUT 20H,AL
1596 pop ax
1597 IRET
1598FloppyInterrupt ENDP
1599
1600SUBTTL Timing routines for floppy disk
1601PAGE +
1602
1603;* Data for timers
1604TimerActive DB 0 ; bit flags for active timers
1605TimerConv DB 50 ; conversion factor for ms => ticks
1606Timer1 DB 0 ; One-shot time till restart intr. rtn.
1607Timer2 DB 0 ; Repetitive 1 Hz timer
1608Timer2count = 20 ; Reload value for timer2
1609
1610MOFFDELAY= 2 ; turn off motor after 2 sec. inactivity
1611
1612;*** SetTimer1 - Arm timer 1
1613;
1614; SetTimer1 will arm the Timer1. Input parameter
1615; values in milliseconds will be converted to timer
1616; ticks.
1617;
1618; ENTRY AX = delay value in milliseconds
1619; EXIT AL = timer ticks
1620; CF set if timer armed
1621; CF clear if zero count passed
1622; USES AX
1623
1624SetTimer1 PROC
1625 TEST AX,AX ; zero count?
1626 JNZ sett10 ; no
1627 CLC
1628 RET
1629
1630sett10: DIV TimerConv
1631 TEST AH,AH ; remainder?
1632 JZ sett11
1633 INC AL ; yes, round up
1634sett11: MOV Timer1,AL
1635 OR TimerActive,1
1636 debug 4,8,<SetTimer1 $b\n>,<ax>
1637 STC
1638 RET
1639SetTimer1 ENDP
1640
1641;*** SetTimer2 - Arm timer 2
1642;
1643; SetTimer2 will set a motor off timeout for the
1644; drive whose parameter block is pointed to by
1645; CS:BX
1646;
1647; ENTRY CS:BX = pointer to per drive info.
1648; EXIT
1649; USES NONE
1650
1651SetTimer2 PROC
1652 TEST TimerActive,2
1653 JNZ sett21
1654 MOV Timer2,Timer2Count
1655 OR TimerActive,2
1656sett21: MOV CS:[BX].Timer,MOFFDELAY
1657 debug 4,8,<SetTimer2\n>,<>
1658 RET
1659SetTimer2 ENDP
1660
1661
1662
1663; FloppyTimer is called every scheduler tick to perform
1664; time related services for the floppy driver. There are
1665; two services performed; rescheduling of interrupt time
1666; service after a head load or motor startup delay, and
1667; a motor turn off service when a drive is not active.
1668;
1669; It's assumed that all registers have been saved by the
1670; caller.
1671
1672 ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING
1673
1674 PUBLIC FloppyTimer
1675FloppyTimer PROC FAR
1676 TEST TimerActive,0ffH ; any timers active?
1677 JNZ fltim1 ; yes
1678 RET ; no, return quickly
1679fltim1: TEST TimerActive,1 ; Timer1 active?
1680 JZ fltim3 ; no
1681 DEC Timer1 ; Timer1 expired?
1682 JNZ fltim3 ; no
1683;* Perform Timer1 service
1684 debug 4,8,<Timer 1 expired\n>,<>
1685 AND TimerActive,NOT 1
1686 CALL FloppyExecute ; push the states around a while
1687 RET ; don't do Timer2 service this time.
1688
1689fltim3: TEST TimerActive,2 ; Timer2 active?
1690 JZ fltim4 ; no
1691 DEC Timer2 ; 1 Hz clock time?
1692 JZ fltim5 ; no
1693fltim4: JMP fltim9
1694fltim5:
1695 debug 4,8,<Timer 2 expired\n>,<>
1696 MOV BL,Timer2count ; reload the counter
1697 MOV Timer2,BL
1698
1699;* Perform Timer2 service
1700 XOR CH,CH ; No active timeouts seen
1701 XOR DI,DI ; Start with drive A
1702TimeOutLoop:
1703 MOV BX,DI
1704 ADD BX,BX
1705 MOV BX,FDinfo[BX] ; Get ptr to drive info
1706 TEST CS:[BX].DrvFlag,Fmotoron ; motor on?
1707 JZ fltim8 ; no
1708 CMP CS:[BX].Timer,0 ; Is timer active for drive?
1709 JZ fltim8 ; No
1710 DEC CS:[BX].Timer ; Yes, another tick has passed
1711 JNZ fltim7
1712 cmp di,Floppy.Current ; Current drive?
1713 jnz fltim6 ; no
1714 test Floppy.Flags,Factive ; device active?
1715 jz fltim6 ; no, go ahead
1716 mov Floppy.State,Error
1717 mov Floppy.ErrCnt,ErrLim ; don't retry this one
1718 mov Floppy.ST0,048H ; set not ready error
1719 call FloppyExecute ; oops, sanity timeout
1720 jmp fltim9
1721fltim6:
1722 AND CS:[BX].DrvFlag,NOT Fmotoron ; stop drive motor
1723 MOV AX,DI
1724 MOV CL,AL
1725 ADD CL,4
1726 MOV AL,1
1727 SHL AL,CL ; Get bit mask for motor on
1728 TEST Floppy.DOR,AL ; Is motor already off?
1729 JE fltim8 ; Yes, go on to next drive
1730 NOT AL ; Get all bits except this motor
1731 AND Floppy.DOR,AL ; Clear this motor on
1732 MOV DX,FD_PSEL
1733 MOV AL,Floppy.DOR
1734 OUT DX,AL ; Turn off motor
1735;; cmp di,Floppy.Current ; Current drive?
1736;; jnz fltim8 ; no
1737;; test Floppy.Flags,Factive ; device active
1738;; jz fltim8 ; no, go on to next drive
1739;; call DumpRegs ; oops, sanity timeout
1740
1741fltim7: INC CH ; Flag still active
1742fltim8: INC DI ; Advance to next drive
1743 CMP DI,WORD PTR NumFloppy ; Any more to check?
1744 JNE TimeOutLoop ; Yes, do them
1745 OR CH,CH ; Need to keep timer active?
1746 JNZ fltim9 ; Yes
1747 AND TimerActive,NOT 2 ; No, clear timeout is active
1748fltim9: RET
1749
1750FloppyTimer ENDP
1751
1752
1753IFDEF DEBUGFLG
1754DumpRegs PROC
1755 push cs
1756 pop ds
1757 debug 4,0fh,<Sanity Timeout!!\n>,<>
1758 mov di,OFFSET Floppy
1759 debug 4,0fh,<Floppy struct\n $x $x $x $x $x $x $x $x\n>,<[di],[di.2],[di.4],[di.6],[di.8],[di.10],[di.12],[di.14]>
1760 debug 4,0fh,< $x $x $x $x $x $x $x $x\n>,<[di.10h],[di.12h],[di.14h],[di.16h],[di.18h],[di.1ah],[di.1ch],[di.1eh]>
1761 call GetDrivePtr
1762 debug 4,0fh,<Drive struct\n $x $x $x $x $x $x $x $x\n>,<[bx],[bx.2],[bx.4],[bx.6],[bx.8],[bx.10],[bx.12],[bx.14]>
1763 debug 4,0fh,< $x $x $x $x\n>,<[bx.16],[bx.18],[bx.20],[bx.22]>
1764 debug 4,0fh,< IMR IRR ISR 8259 status\n>,<>
1765 mov al,0ah
1766 out 20h,al
1767 in al,20h
1768 mov bl,al
1769
1770 mov al,0bh
1771 out 20h,al
1772 in al,20h
1773 mov cl,al
1774 in al,21h
1775 debug 4,0fh,< $b $b $b\n>,<ax,bx,cx>
1776 debug 4,0fh,<765 status, data\n>,<>
1777 mov dx,FD_PSTAT
1778 in al,dx
1779 mov bl,al
1780 mov dx,FD_PDAT
1781 in al,dx
1782 debug 4,0fh,< $b $b\n>,<bx,ax>
1783 sti
1784dmpr0: jmp dmpr0
1785DumpRegs ENDP
1786ENDIF ;DEUBGFLAG
1787
1788SUBTTL Routines shared between Floppy and Hard disk drivers
1789PAGE +
1790
1791;*** Setup - Set request parameters into local structure.
1792;
1793; Setup sets the Unit, First, Addr, Count and Flags fields in the
1794; device structure which are used to drive the I/O. The following
1795; flags are affected:
1796; Fwrite This is a write request, not a read
1797; Fverify This is a write with verify (verify when write
1798; is cleared).
1799; Other fields are copied from the DOS request packet.
1800;
1801; ENTRY SI Pointer to device variables
1802; ES:BX Current request
1803; AL Unit number
1804; DI BPB for drive
1805; DS CS
1806;
1807; EXIT The following variables are set
1808; [SI].Unit
1809; [SI].First The hidden sectors are added
1810; [SI].RealAddr
1811; [SI].Count
1812; [SI].Flags
1813
1814 ASSUME CS:BiosSeg,DS:BiosSeg
1815
1816Setup PROC
1817 MOV AX,ES:[BX].RqCount
1818 MOV [SI].Count,AX ; Set number of sectors to do
1819 MOV AX,ES:[BX].RqAddr
1820 MOV WORD PTR [SI].RealAddr,AX
1821 MOV AX,ES:[BX].RqAddr+2
1822 MOV WORD PTR [SI].RealAddr+2,AX ; Copy data address
1823 MOV AL,ES:[BX].RqUnit ; Get unit number
1824 MOV [SI].Unit,AL ; Set drive needed
1825 MOV AX,ES:[BX].RqFirst ; Get the starting sector number
1826 ADD AX,[DI].BPBhidsec ; Add # of hidden sectors
1827 MOV [SI].First,AX ; Set 1st sector of I/O
1828 and [SI].Flags,Factive+F2step ; mask excess flags
1829 CMP ES:[BX].RqCmd,4 ; Is this a read?
1830 JE SetupDone ; Yes, all done
1831 OR [SI].Flags,Fwrite ; No, flag this is a read
1832 CMP ES:[BX].RqCmd,9 ; Write with verify?
1833 JNE SetupDone ; No, just write
1834 OR [SI].Flags,Fverify ; Yes, set to verify too
1835SetupDone:
1836 RET
1837Setup ENDP
1838
1839
1840;*** MapSector - compute head, sector, cylinder
1841;
1842; MapSector takes the fields set up by Setup and figures out the
1843; head, cylinder and sector involved. If the request involves
1844; multiple sectors, it figures out how many can be done at once
1845; based on the number of sectors left on the track and that the
1846; target address' offset does not wrap around 64k (the DMA on the
1847; PC uses a 20 bit address, but the high 4 bits do not change when
1848; the low 16 cycle back to 0). If the request wraps around 64k, it
1849; is split into 2 or 3 pieces which are all data before wrap, after
1850; wrap and the wrap itself. The wrap itself is transferred via a temp
1851; buffer (ScratchBuffer).
1852;
1853; ENTRY SI Pointer to device variables
1854; ES:BX Current request
1855; AL Unit number
1856; DI BPB for drive
1857; DS CS
1858; EXIT The following variables are set
1859; [SI].Flags
1860; [SI].Head
1861; [SI].Cyl
1862; [SI].Sector
1863; [SI].NumSectors
1864; [SI].NumBytes
1865; [SI].Addr
1866; USES AX,CX,DX,DI
1867;
1868
1869MapSector PROC
1870 PUSH ES
1871 les CX,[SI].RealAddr
1872 MOV WORD PTR [SI].Addr,CX ; copy RealAddr to Addr
1873 MOV WORD PTR [SI].Addr+2,ES
1874 AND [SI].Flags,NOT Fwrap1 ; Clear buffer wrap flag
1875
1876; Calculate the head, cylinder and sector of the start of the request
1877; from [SI].First
1878 POP ES
1879 MOV AX,[SI].First
1880 XOR DX,DX
1881 DIV [DI].BPBtrksiz ; Divide by sectors/track
1882;; INC DL
1883 MOV [SI].Sector,DL ; Set sector to start at
1884 XOR DX,DX
1885 DIV [DI].BPBnhead ; Divide by number of heads
1886 MOV [SI].Head,DL ; Set head number
1887 MOV [SI].Cyl,AX ; Set cylinder number
1888 debug 8,4,<Cyl $d Hd $b Sec $b >,<ax,dx,<word ptr [SI].Sector>>
1889;
1890; Now see how many sectors of request can be done. The floppy
1891; controller will not advance tracks, but will allow reading or
1892; writing the remaining sectors on the track.
1893;
1894 MOV AX,[DI].BPBtrksiz
1895 SUB AL,[SI].Sector ; AL = # of sectors left on
1896 ; track after desired.
1897 XOR AH,AH
1898;; inc ax
1899 CMP AX,[SI].Count ; Is whole request on this cyl?
1900 JB maps2 ; No, can only do what is left
1901 MOV AX,[SI].Count ; Yes, use the actual # wanted
1902maps2:
1903 MOV [SI].Numsectors,AX ; Set number to do this time
1904;
1905; Now have to normalize offset (add in paragraph) and then see if adding
1906; [SI].Numsectors causes overflow. If it does, DMA will trash memory, so
1907; decrement Numsectors and loop.
1908;
1909 MOV AX,WORD PTR([SI].Addr+2)
1910 MOV CL,4
1911 SHL AX,CL ; Convert para to offset
1912 ADD AX,WORD PTR [SI].Addr ; Add in offset
1913 MOV CX,AX ; Save offset of buffer
1914maps4:
1915 MOV AX,[DI].BPBsecsiz
1916 MUL [SI].NumSectors ; Get # bytes in transfer
1917 MOV [SI].NumBytes,AX ; Set # bytes involved
1918 ADD AX,CX ; Get final offset
1919 JAE maps6 ; No overflow, DMA will be ok
1920 OR [SI].Flags,Fwrap2 ; Flag we will be using scratch
1921 DEC [SI].NumSectors ; Overflow, try using one less
1922 JNZ maps4
1923;
1924; If we got here, no sectors can be transferred before the 64K
1925; boundary. One sector must be transferred through a scratch buffer.
1926;
1927 debug 12,10h,<MapSector $x $x >,<ax,cx>
1928 INC [SI].NumSectors ; Doing 1 sector of I/O
1929 OR [SI].Flags,Fwrap1 ; Flag we are using scratch
1930 MOV AX,CS
1931 MOV DI,OFFSET ScratchBuffer
1932 MOV WORD PTR([SI].Addr),DI
1933 MOV WORD PTR([SI].Addr+2),AX ; Change buffer to scratch
1934 TEST [SI].Flags,Fwrite ; Doing a write?
1935 JE maps6 ; No, All done
1936 PUSH ES
1937 PUSH DS
1938 PUSH SI
1939 MOV ES,AX ; ES:DI = scratch buffer
1940 mov cx,[SI].NumBytes
1941 LDS SI,[SI].RealAddr ; DS:SI = Data buffer
1942 CLD
1943REP MOVSB ; Copy the write buffer
1944 POP SI
1945 POP DS
1946 POP ES
1947maps6:
1948 RET
1949MapSector ENDP
1950
1951
1952
1953
1954;*** DMAsetup - Set the DMA channel up to do the I/O
1955;
1956; ENTRY AL = DMA mode
1957; AH = DMA channel number (2 or 3 only)
1958; SI = pointer to device parameters
1959; USES AX,CX,DX
1960;
1961
1962DMAsetup PROC
1963 PUSH AX
1964 XCHG AH,AL
1965 OR AL,4
1966 OUT PDMA+10,AL ; set channel's mask bit
1967 OUT PDMA+12,AL ; clear byte pointer F/F
1968 pop ax
1969 push ax ; restore AH, AL
1970 OR AL,AH ; add channel number to command
1971 OUT PDMA+11,AL ; Set DMA mode
1972 MOV DX,PDMA
1973 ROL AH,1
1974 ADD DL,AH
1975 MOV AX,WORD PTR [SI].Addr+2 ; Get segment of addr
1976 MOV CL,4
1977 ROL AX,CL ; Convert para to bytes
1978 MOV CH,AL ; CH = 4 bits ROLed around
1979 AND AL,0F0H ; Lose high bits rotated around
1980 ADD AX,WORD PTR [SI].Addr ; Add in offset value
1981 ADC CH,0 ; Add in any carry
1982 OUT DX,AL ; Output low byte of address
1983 MOV AL,AH
1984 OUT DX,AL ; Output high byte of address
1985 inc dx ; address `word' count register
1986 MOV AX,[SI].NumBytes ; # bytes in request
1987 dec ax
1988 OUT DX,AL
1989 MOV AL,AH
1990 OUT DX,AL ; Tell DMA how many bytes
1991 pop ax ; get back channel number
1992 mov dl,PDMAX
1993 add dl,ah
1994 MOV AL,CH
1995 AND AL,0FH ; Only 4 bits are good
1996 OUT DX,AL ; Output highest 4 bits of address
1997 MOV AL,AH ; Channel to start
1998 OUT PDMA+10,AL ; Clear channel's mask bit
1999 RET
2000DMAsetup ENDP
2001
2002;*** DoneRequest - Mark a request complete, setup to start next one
2003;
2004; DoneRequest does common processing needed when a request
2005; has been completed. It will reset the device state,
2006; dequeue the request, mark it complete, restart the
2007; process and restart any process waiting on ScratchBuffer
2008; if this request had reserved it.
2009;
2010; ENTRY SI Pointer to head of queue
2011; DI Pointer to device information
2012; EXIT ES:BX Next request
2013; USES AX,BX,DX,BP,ES
2014
2015
2016DoneRequest PROC
2017 push cs
2018 pop ds
2019 ASSUME ds:BiosSeg
2020 MOV [DI].ErrCnt,0 ; Reset error count
2021 MOV [DI].State,Idle ; Assume will be idle
2022 MOV DX,PullRequest
2023 CALL DosFunction ; Pull the current request out
2024 JZ dnrq2 ; Nothing really completed
2025 MOV AX,[DI].Count ; Get I/O left to do
2026 SUB ES:[BX].RqCount,AX ; Adjust requested count by residual
2027 OR ES:[BX].RqStatus,0100h ; set done bit
2028 MOV AX,ES ; AX:BX = Request completed
2029 MOV DX,ContinueProcess
2030 CALL DosFunction ; Make process run again
2031 CMP WORD PTR [SI]+2,0 ; Is there another request to do?
2032 JZ dnrq2 ; No, let device shut down
2033 MOV [DI].State,Start ; Yes, start up next request
2034dnrq2:
2035 test [DI].Flags,Fwrap2 ; had this request used ScratchBuffer?
2036 jz dnrq4 ; no
2037 SemSig ScratchBufSem ; let anyone waiting proceed
2038 and [DI].Flags,NOT Fwrap2
2039dnrq4: ; If both the fixed and floppy drivers
2040 push bx ; are idle, reset the busy flag and
2041 cmp Floppy.State,Idle ; continue any processes that were
2042 jne dnrq5 ; waiting for it.
2043 cmp Fixed.State,Idle
2044 jne dnrq5
2045 mov SemDiskIO,0
2046 mov ax,ds
2047 mov bx,offset SemDiskIO
2048 mov dx,ContinueProcess
2049 call DosFunction
2050dnrq5:
2051 pop bx
2052 ret
2053DoneRequest ENDP
2054
2055
2056; FDGetBPB returns a pointer to the floppy disk BPB for the
2057; selected media byte. The BPB contains various drive parameters
2058; such as physical disk dimensions and the size of FATs and the
2059; root directory.
2060;
2061; Input: AH = Media byte
2062; AL = Drive number
2063; Destroys: None
2064; Output: CS:DI = Pointer to BPB
2065
2066 ASSUME DS:NOTHING,ES:NOTHING
2067
2068FDGetBPB PROC
2069
2070 PUSH AX
2071 PUSH BX
2072 PUSH CX
2073 PUSH DX ; Save regs
2074 MOV CL,AH ; Copy media value
2075 AND CL,0F8H ; Look at just top 5 bits
2076 CMP CL,0F8H ; Valid media byte?
2077 JE BPBGood ; Yes
2078 MOV AH,0FEH ; No, make it 8 sector 1 sided
2079BPBgood:
2080 MOV BL,AL ; Get pointer to per drive info.
2081 XOR BH,BH
2082 ADD BX,BX
2083 MOV DI,CS:FDinfo[BX]
2084 CMP AH,CS:[DI].BPBmediab ; already set?
2085 JE BPBdone ; yes, don't bother rebuilding
2086 MOV AL,1 ; Assume will have 1 FAT sector
2087 MOV BX,64*256+8 ; Assume # dir = 64, 8 sector
2088 MOV CX,40*8 ; Assume 320 sectors/disk
2089 MOV DX,1*256+1 ; Assume 1 head, 1 sector/allocate
2090 TEST AH,2 ; Is drive 8 or 9 sector?
2091 JNZ BPBKnowSectors ; It's 8, we assumed right
2092 INC AL ; 9 sector, incr # of FAT sectors
2093 INC BL ; Set we have 9 sectors/cylinder
2094 ADD CX,40 ; Increase size to 360 sectors
2095BPBKnowSectors:
2096 TEST AH,1 ; Is disk double sided?
2097 JE BPBKnowHeads ; No, we guessed right
2098 ADD CX,CX ; Double size of disk
2099 MOV BH,112 ; Increase # of directory entries
2100 INC DH ; Set 2 sectors/allocation unit
2101 INC DL ; Set 2 heads
2102BPBKnowHeads:
2103 MOV CS:[DI].BPBsecpau,DH ; Set sectors/allocation unit
2104 MOV BYTE PTR CS:[DI].BPBndir,BH ; Set # of directory entries
2105 MOV CS:[DI].BPBnsec,CX ; Set size of disk in sectors
2106 MOV CS:[DI].BPBmediab,AH ; Set media byte
2107 MOV BYTE PTR CS:[DI].BPBnfatsec,AL ; Set number of FAT sectors
2108 MOV BYTE PTR CS:[DI].BPBtrksiz,BL ; Set sectors/track
2109 MOV BYTE PTR CS:[DI].BPBnhead,DL ; Set # of heads
2110BPBdone:
2111 POP DX
2112 POP CX
2113 POP BX
2114 POP AX
2115 RET
2116FDGetBPB ENDP
2117
2118
2119; HDGetBPB returns a pointer to the hard disk BPB for the
2120; selected unit. The BPB contains various drive parameters
2121; such as physical disk dimensions and the size of FATs and the
2122; root directory.
2123;
2124; Input: AL = Drive number
2125; Destroys: None
2126; Output: CS:DI = Pointer to BPB
2127
2128 ASSUME DS:NOTHING,ES:NOTHING
2129
2130HDGetBPB PROC
2131 PUSH BX
2132 MOV BL,AL ; Get pointer to per drive info.
2133 XOR BH,BH
2134 ADD BX,BX
2135 MOV DI,CS:HDinfo[BX]
2136 POP BX
2137 RET
2138HDGetBPB ENDP
2139
2140
2141 ASSUME DS:NOTHING,ES:NOTHING
2142
2143BlockIfLocked Proc Near ; Block the current process if it has
2144 pushf ; been locked out by an Int 13 request.
2145bifl1: cli ; Otherwise, set the busy flag to block
2146 cmp SemInt13,0 ; out Int 13 requests.
2147 jz bifl2
2148 push dx
2149 push cx
2150 push bx
2151 push ax
2152 mov ax,cs
2153 mov bx,offset SemInt13
2154 xor cx,cx
2155 mov dx,BlockProcess
2156 call DosFunction
2157 pop ax
2158 pop bx
2159 pop cx
2160 pop dx
2161 jmp bifl1
2162bifl2:
2163 mov SemDiskIO,1
2164 popf
2165 ret
2166BlockIfLocked endp
2167
2168SUBTTL Routines that interface to hard disk controller
2169PAGE +
2170
2171;*** HDCommand - send a command to the hard disk controller
2172;
2173; HDCommand will send the previously set up command block
2174; to the hard disk controller.
2175;
2176; ENTRY AL = value to be put in interrupt/DMA mask
2177; EXIT AL = status port value
2178; USES AX,CX,DX,SI
2179
2180HDCommand PROC
2181 mov dx,HD_PSEL ; point to select port
2182 out dx,al
2183;; mov cx,10 ;BUGBUG - timing prob. w/ expansion box?
2184;;hdcom0: loop hdcom0 ;BUGBUG - timing prob. w/ expansion box?
2185 inc dx ; point to mask port
2186 out dx,al
2187 mov dx,HD_PSTAT
2188hdcom1: in al,dx ; get status
2189 and al,0FH
2190 cmp al,0DH ; test for busy, command/data, request
2191 jnz hdcom1
2192 mov si,OFFSET Fixed.DCB
2193 mov cx,6
2194 cld
2195 dec dx ; point to data port
2196hdcom2: lodsb
2197 out dx,al
2198 loop hdcom2
2199 inc dx
2200;; mov cx,10 ;BUGBUG - timing prob. w/ expansion box?
2201;;hdcom3: loop hdcom3 ;BUGBUG - timing prob. w/ expansion box?
2202 in al,dx
2203 ret
2204HDCommand ENDP
2205
2206;*** HDWaitReq - wait for request bit in status register
2207;
2208; HDWaitReq will pause until the request bit in the hard disk
2209; status register is set.
2210;
2211; ENTRY
2212; EXIT AL = status byte
2213; USES AX,DX
2214
2215HDWaitReq PROC
2216 mov dx,HD_PSTAT
2217 in al,dx
2218 test al,01h ; request bit?
2219 jz HDWaitReq
2220 ret
2221HDWaitReq ENDP
2222SUBTTL Routines that interface to floppy disk controller
2223PAGE +
2224
2225;*** GetDrivePtr - compute ptr to per drive info.
2226;
2227; GetDrivePtr returns a pointer to the per-drive information
2228; for the current drive. Should not be called before the
2229; current drive is set up by Sel765 in state CALC.
2230;
2231; EXIT BX = pointer to per drive table
2232; USES BX
2233
2234GetDrivePtr PROC
2235 mov bx,cs:Floppy.Current
2236 add bx,bx
2237 mov bx,cs:FDinfo[bx]
2238 ret
2239GetDrivePtr ENDP
2240
2241
2242; GetFloppyParam is called to get a disk parameter from the parameter
2243; block set up by the BIOS. This block allows disk parameters to be changed
2244; from the standard.
2245;
2246; Input: AL = parameter desired (see FloppyParam structure)
2247; Destroys: AX
2248; Output: AL = parameter byte desired
2249
2250GetFloppyParam PROC
2251 PUSH DS
2252 PUSH BX
2253 XOR AH,AH
2254 MOV BX,AX
2255 XOR AX,AX
2256 MOV DS,AX ; Point to INT area
2257 LDS AX,DWORD PTR DS:(4*1EH) ; Get pointer to param block
2258 ADD BX,AX ; Add in block offset
2259 MOV AL,[BX]
2260 POP BX
2261 POP DS
2262 RET
2263GetFloppyParam ENDP
2264
2265
2266
2267; Recalibrate the current drive. Clear Restore flag, set cylinder to
2268; unknown and issue command to controller.
2269;
2270; Destroys: AX,BX,DX
2271;
2272
2273Rcl765 PROC
2274 AND CS:[BX].DrvFlag,NOT Frestor ; Have restored drive
2275 MOV CS:[BX].CurCyl,-1 ; Flag don't know where we are
2276 MOV AL,FD_CRESET
2277 CALL Put765 ; Put out reset command
2278 MOV AX,Floppy.Current ; Get current drive
2279 CALL Put765 ; Tell controller which drive
2280 RET
2281Rcl765 ENDP
2282
2283
2284; Reset the controller.
2285;
2286; Destroys: AX,CX,DX
2287;
2288
2289Rst765 PROC
2290 MOV AL,CS:Floppy.DOR
2291 AND AL,NOT(DORmask)
2292 MOV DX,FD_PSEL
2293 OUT DX,AL
2294 MOV CX,10000
2295RstDelayLoop:
2296 loop RstDelayLoop
2297 OR AL,DORmask
2298 MOV CS:Floppy.DOR,AL ; Update value
2299 OUT DX,AL
2300 RET
2301Rst765 ENDP
2302
2303
2304; Load the drive specs into the controller.
2305;
2306; Destroys: AX,DX
2307;
2308
2309Spec765 PROC
2310 MOV AL,FD_CSPEC
2311 CALL Put765
2312 MOV AL,Spec1
2313 CALL GetFloppyParam
2314 CALL Put765
2315 MOV AL,Spec2
2316 CALL GetFloppyParam
2317 CALL Put765
2318 RET
2319Spec765 ENDP
2320
2321
2322; Get the interrupt status from the controller and into AX
2323;
2324; Destroys: AX,CX,DX
2325;
2326
2327Sense765 PROC
2328 MOV AL,FD_CSENSE ; Get status
2329 CALL Put765
2330 CALL Get765 ; Read ST0
2331 PUSH AX ; Save status
2332 CALL Get765 ; Read PCN (present cylinder number)
2333 POP AX ; Restore status
2334 MOV CL,6
2335 SHR AL,CL ; Shift bits down
2336 AND AX,3 ; Leave only error bits
2337 RET
2338Sense765 ENDP
2339
2340
2341; Select the current drive. Return carry set if must wait until drive is
2342; ready. FloppyExecute will be called again when the drive is ready. The
2343; code must wait either for a motor start or head load delay, otherwise it
2344; returns with carry clear.
2345;
2346; Destroys: AX,BX,CX,DX
2347;
2348
2349Sel765 PROC
2350 MOV DX,FD_PSEL ; set DX = Digital Output Register
2351 MOV CL,Floppy.Unit ; Get unit we want to use
2352 XOR CH,CH ; CX = wanted unit
2353 CMP Single,0 ; Single drive system?
2354 JE Sel765Double ; No, Unit is accurate
2355 MOV CL,CH ; Yes, there is only drive 0
2356Sel765Double:
2357 CMP CX,Floppy.Current ; Wanted same as current?
2358 MOV Floppy.Current,CX ; Set new current unit
2359 JNE SelectUnit ; No, must select new drive
2360 ADD CL,4
2361 MOV AL,1
2362 SHL AL,CL ; AL = Bit for drive's motor on
2363 TEST AL,Floppy.DOR ; Is the drive's motor still on?
2364 JE SelectUnit ; No, must turn it back on
2365 MOV AL,Floppy.DOR
2366 OUT DX,AL ; ? For some reason output value again
2367 CLC ; Clear carry, don't have to wait
2368 RET
2369
2370SelectUnit:
2371 MOV AL,NOT(3) ; Drive select is low 2 bits
2372 AND AL,Floppy.DOR ; Lose old select bits
2373 OR AL,DORmask
2374 MOV CL,BYTE PTR Floppy.Current ; get unit number
2375 OR AL,CL ; Put in new select bits
2376 MOV Floppy.DOR,AL ; Save new bits
2377 ADD CL,4
2378 MOV AL,1
2379 SHL AL,CL ; Get bit for motor is on
2380 TEST AL,Floppy.DOR ; Is drive's motor on?
2381 JE SelectStartMotor ; No, must start motor
2382 MOV AL,Floppy.DOR
2383 OUT DX,AL ; Load the head
2384 MOV AX,DelayLoad ; Load head delay
2385 CALL SetTimer1
2386 RET
2387
2388SelectStartMotor:
2389 OR Floppy.DOR,AL ; Add in motor start bit
2390 MOV AL,Floppy.DOR
2391 OUT DX,AL ; Start the motor
2392 MOV AL,DelayMotor
2393 CALL GetFloppyParam ; Get the proper delay time in 1/8 sec
2394 mov cl,125
2395 mul cl ; convert to milliseconds
2396 CALL SetTimer1 ; Set timer for motor startup
2397 RET
2398Sel765 ENDP
2399
2400
2401; Seek to the correct cylinder. Set carry if have to wait for operation
2402; to complete (we are not on right cylinder).
2403;
2404; Destroys: AX,BX,DX
2405;
2406
2407Seek765 PROC
2408 MOV AX,Floppy.Cyl ; Get cylinder wanted
2409 CMP AX,CS:[BX].CurCyl ; Already on cylinder?
2410 JE SeekDone ; Yes, return with carry clear
2411 MOV CS:[BX].CurCyl,AX ; Set the new current cylinder
2412 MOV AL,FD_CSEEK
2413 CALL Put765 ; Seek command
2414 MOV AL,Floppy.Head ; Get head desired
2415 SHL AL,1
2416 SHL AL,1 ; Move head # 2 bits left
2417 ADD AL,BYTE PTR Floppy.Current ; Low 2 bits are unit (hhuu)
2418 CALL Put765 ; Put out drive and head select
2419 MOV AX,Floppy.Cyl
2420 TEST Floppy.Flags,F2step ; Need to double step?
2421 JE SeekNoDouble ; No
2422 ADD AX,AX ; Yes, double cylinder number
2423SeekNoDouble:
2424 CALL Put765 ; Give controller the cylinder
2425 STC ; Set carry, must wait for seek intr.
2426SeekDone:
2427 RET
2428Seek765 ENDP
2429
2430
2431
2432; Start the Read/write. Set up the DMA channel and give a read or write
2433; command to the controller depending on flag.
2434;
2435; Destroys: AX,CX,DX
2436;
2437
2438RdWr765 PROC
2439 mov ah,FD_DMA
2440 mov si,OFFSET Floppy
2441 TEST Floppy.Flags,Fwrite ; Is this a write?
2442 JNE WriteSetup ; Yes
2443 MOV AL,DMA_READ ; No, read
2444 CALL DMAsetup ; Set up the DMA
2445 MOV AL,FD_CREAD ; Want to read
2446 JMP SHORT RdWrLoc ; Now put out rest of command
2447
2448WriteSetup:
2449 MOV AL,DMA_WRITE
2450 CALL DMAsetup ; Set DMA up for write
2451 MOV AL,FD_CWRITE ; Want to write
2452RdWrLoc:
2453 CALL Put765 ; Put out command
2454 MOV AL,Floppy.Head
2455 ADD AL,AL
2456 ADD AL,AL ; Form HHxx Binary
2457 ADD AL,BYTE PTR Floppy.Current ; Form HHUU
2458 CALL Put765 ; Output unit and head
2459 MOV AX,Floppy.Cyl
2460 CALL Put765 ; Output cylinder
2461 MOV AL,Floppy.Head
2462 CALL Put765 ; Output head again?
2463 MOV AL,Floppy.Sector
2464 inc al
2465 CALL Put765 ; Output sector
2466 MOV AL,SectorSize
2467 CALL GetFloppyParam ; Get sector size code
2468 CALL Put765 ; Tell controller sector size
2469 MOV AL,CylSize
2470 CALL GetFloppyParam ; Get number of sectors/cylinder
2471 CALL Put765 ; Tell controller
2472 MOV AL,DataGap ; Gap length for read/write
2473 CALL GetFloppyParam
2474 CALL Put765 ; Tell controller gap length
2475 MOV AL,ValueDTL
2476 CALL GetFloppyParam ; Get value for DTL
2477 CALL Put765 ; Since bytes/sector#0, this is a
2478 ; meaningless value, but controller
2479 ; wants to see something
2480 RET
2481RdWr765 ENDP
2482
2483
2484
2485; Fini765 gets the completion status.
2486;
2487; Destroys: AX,CX,DX
2488; Returns: AL
2489;
2490
2491Fini765 PROC
2492 push es
2493 push di
2494 push cs
2495 pop es
2496 mov di,OFFSET Floppy.ST0
2497 MOV CX,7
2498fini1: CALL Get765
2499 stosb
2500 loop fini1
2501 mov al,Floppy.ST0
2502 mov cl,6
2503 SHR AL,CL
2504 AND AX,3 ; Mask down to value to return
2505 pop di
2506 pop es
2507 RET
2508Fini765 ENDP
2509
2510
2511
2512; Put765 writes a command to the controller.
2513;
2514; Input: AL = value
2515; Destroys: AX,DX
2516;
2517
2518Put765 PROC
2519 PUSH AX ; Save the value to write
2520PutWaitLoop:
2521 MOV DX,FD_PSTAT
2522 IN AL,DX ; Get status
2523 AND AL,FD_SDIO+FD_SRQM
2524 CMP AL,FD_SRQM ; Controller ready for data?
2525 JNE PutWaitLoop ; No, keep waiting
2526 POP AX ; Get value back
2527 MOV DX,FD_PDAT
2528 OUT DX,AL ; Put out value
2529 RET
2530Put765 ENDP
2531
2532
2533; Get765 gets a value back from the controller into AL.
2534;
2535; Destroys: AX,DX
2536; Returns: AL
2537;
2538
2539Get765 PROC
2540 MOV DX,FD_PSTAT
2541 IN AL,DX ; Get status
2542 AND AL,FD_SDIO+FD_SRQM
2543 CMP AL,FD_SDIO+FD_SRQM ; Controller data available?
2544 JNE Get765 ; No, wait for it
2545 MOV DX,FD_PDAT
2546 IN AL,DX ; Get value from controller
2547 ret
2548Get765 ENDP
2549
2550Code ENDS
2551 END
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.OBJ
new file mode 100644
index 0000000..daf953a
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMDSK.OBJ
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.ASM b/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.ASM
new file mode 100644
index 0000000..6cfefbe
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.ASM
@@ -0,0 +1,1424 @@
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
54FALSE EQU 0
55TRUE EQU NOT FALSE
56
57CVERS equ 01 ; update version number!!
58CREV equ 08
59
60BLANK equ TRUE ; blank screen during data r/w
61INBIOS equ TRUE ; link with BIOS
62ANSI equ TRUE ; include ANSI escape sequences
63 LINE25 equ TRUE ; special 25th line like VT52
64EAGLE equ TRUE ; Eagle PC ROM botches CRT_LEN
65
66
67subttl Screen Information Block Definition
68page
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;------------------------------------------------------------------------
79MaxSEG equ 2 ; NOTE: assumption is made in the
80 ; code that all SIB's have same
81 ; number os SEGs
82SEGst struc
83SizeNeeded dw 0 ; needed size for seg, (0 = unused)
84MemFlag dw ? ; maintened by system (0 = in mem)
85MPointer dd ? ; vaild iff MemFlag == 0
86SEGst ends
87
88;------------------------------------------------------------------------
89MaxSIB equ 8 ; maximum number of Screens
90
91
92IF ANSI
93TermSize EQU 20 ; max. size of terminal emulation state
94ENDIF
95
96SIBst struc
97ctlS db 0 ; if the screen is NOT frozen = 0
98 ; NOTE: this field should be the
99 ; FIRST of each SIB !! (see ConWrit)
100OffsetVal dw 7 ; start of Seg Descriptors
101SegCnt dw MaxSeg ; max number of Segments
102SIBlen dw (SIZE SIBst) ; length of the SIB
103;--- Segments
104 db ((SIZE SEGst) * MaxSeg) dup (?)
105;--- PC video state info
106xCRT_MODE DB ?
107xCRT_COLS DW ?
108xCRT_LEN DW ?
109xCRT_START DW ?
110xCURSOR_POSN DW 8 DUP(?)
111xCURSOR_MODE DW ?
112xACTIVE_PAGE DB ?
113xADDR_6845 DW ?
114xCRT_MODE_SET DB ?
115xCRT_PALETTE DB ?
116xTERM_STATE DB TermSize DUP(?)
117SIBst ends
118
119
120subttl Request packet definitions
121page
122
123;------------------------------------------------------------------------
124; Request packet offset definitions
125;
126
127CMDLEN = 0 ;LENGTH OF THIS COMMAND
128UNIT = 1 ;SUB UNIT SPECIFIER
129CMD = 2 ;COMMAND CODE
130STATUS = 3 ;STATUS
131MEDIA = 13 ;MEDIA DESCRIPTOR
132TRANS = 14 ;TRANSFER ADDRESS
133COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS
134START = 20 ;FIRST BLOCK TO TRANSFER
135
136
137subttl IBM-PC ROM Data area Locations
138page
139
140;------------------------------------------------------------------------
141; IBM-PC ROM Data area Locations
142;
143
144RomData SEGMENT AT 40H
145 ORG 1AH
146BufferHead DW ?
147BufferTail DW ?
148KeyBuffer DW 16 DUP (?)
149KeyBufLen equ ($-KeyBuffer) ; length of KeyBuffer
150
151 ORG 49H
152CRT_MODE DB ?
153CRT_COLS DW ?
154CRT_LEN DW ?
155CRT_START DW ?
156CURSOR_POSN DW 8 DUP(?)
157CURSOR_MODE DW ?
158ACTIVE_PAGE DB ?
159ADDR_6845 DW ?
160CRT_MODE_SET DB ?
161CRT_PALETTE DB ?
162
163CrtLen EQU ($-CRT_MODE) ; length of screen state area
164RomData ENDS
165
166MonoSc SEGMENT AT 0B000H
167;--- 4k of screen memory
168MonoSc ENDS
169
170ColorSc SEGMENT AT 0B800H
171;--- 16k of screen memory
172ColorSc ENDS
173
174BRKADR equ 006CH ; Break vector address
175
176
177subttl Device Header
178page
179
180
181BiosSeg group Code,BiosInit
182Code Segment byte public 'CODE'
183
184;------------------------------------------------------------------------
185; Device Header
186;
187
188assume cs:Code,ds:NOTHING,es:NOTHING,ss:NOTHING
189
190 PUBLIC CONDEV
191IF INBIOS
192 extrn AUXDEV:FAR
193CONDEV dd AUXDEV
194ELSE
195CONDEV dw 0FFFFh,0FFFFh
196ENDIF ;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
208ComTbl:
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
232ComTblEnd:
233
234CTSIZE equ (ComTblEnd - ComTbl)/2 ; number of table entries
235
236
237subttl Device Data Area
238page
239
240;------------------------------------------------------------------------
241; Device Data Area
242;
243
244SaveFlg db 0 ; Screen being saved flag, (true = 1)
245IF INBIOS
246 EXTRN DosFunction:DWORD
247ELSE
248DosFunction dd ? ; pointer to dos "helper" functions
249ENDIF ;INBIOS
250AltAH db 0 ; Side buffer for input
251CurrSc dw 0 ; Current screen number
252CurrSIB dw SIB ; offset to the current SIB
253SIB SIBst MaxSIB dup (<>) ; allocate room for SIB's
254
255IF EAGLE
256ScreenLen 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
264ENDIF
265
266
267IFDEF DEBUGFLG
268IF INBIOS
269 EXTRN BUGBITS:BYTE,DPRINTF:NEAR
270ELSE
271BUGBITS db 0ffh,0ffh
272ENDIF
273ENDIF
274
275subttl Device Entry Points
276page
277
278;------------------------------------------------------------------------
279; 2.0 Interrupt Routine (Not Used)
280;
281
282EntryP proc far
283Entry: ret
284EntryP endp
285
286
287;------------------------------------------------------------------------
288; 2.0 Strategy Routine, main entry point
289;
290; entry
291; ES:BX points to Request packet
292;
293
294StratP proc far
295
296Strategy:
297IF INBIOS
298 extrn Interrupt:NEAR
299
300 push si
301 mov si,OFFSET CS:ComTbl
302 jmp Interrupt
303ELSE
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
328ENDIF ;INBIOS
329
330StratP endp
331
332
333subttl Exit Routines
334page
335
336;------------------------------------------------------------------------
337; Exit Routines, Common to all device functions
338;
339
340IF INBIOS
341 extrn StatusComplete:NEAR,StatusError:NEAR,StatusDevReady:NEAR
342 extrn CmdErr:NEAR
343ELSE
344
345assume ds:NOTHING,es:NOTHING
346
347StatusDevReady:
348 mov ah,00000011b ; device busy
349 jmp short errEx
350
351CmdErr:
352 mov al,3 ; Unknown command Error
353StatusError:
354 mov ah,10000001b
355 jmp short errEx
356
357ExitP proc far
358StatusComplete: mov ah,00000001b
359errEx: 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
372ExitP endp
373
374ENDIF ;INBIOS
375
376
377subttl Break - Break interrupt routine
378page
379
380;------------------------------------------------------------------------
381; Break interrupt routine
382;
383
384assume ds:NOTHING,es:NOTHING
385
386Break 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
401brk1:
402 iret
403Break ENDP
404
405SUBTTL Keyboard interrupt routine
406PAGE
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
417OldKeyInterrupt DD ?
418KeySem db 0 ; non-zero if someone waiting on input
419
420KeyboardInterrupt 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)
438kbi1:
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
445kbi2:
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
462NoKey:
463 IRET
464KeyBoardInterrupt 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
482OldKbdHandler dd ?
483ScrnIoOk dd ?
484
485;-------------------------------------------------------------
486
487KeyBoardHandler proc far
488 or ah,ah
489 je DoLocalRead
490 cmp ah,1
491 je DoLocalStat
492OldKBint:
493 jmp [OldKbdHandler]
494
495DoLocalStat:
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
505DoInt16 LABEL FAR ; entry for ChrIn
506DoLocalRead:
507 push ax
508 push bx
509 push cx
510 push dx
511DoLocalRd1:
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
523DoLocalRd2:
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
538LocalRead:
539 pop dx
540 pop cx
541 pop bx
542 pop ax
543 jmp [OldKbdHandler] ; read the character and return
544
545KeyBoardHandler endp
546
547
548subttl $ConRead - Console Input (Read)
549page
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
560assume 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
567jgl2: 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
573ConRLoop:
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
581sjp0:
582 call ChrIn
583 stosb
584; loop ConRLoop
585 loop jgl3
586CRExit: jmp StatusComplete
587
588jgl3: jmp ConRLoop
589
590subttl ChrIn - Read a single character In
591page
592
593;------------------------------------------------------------------------
594; Read a single character In
595;
596; exit:
597; Character in AL
598;
599; modifies: AX
600;
601
602assume ds:NOTHING,es:NOTHING
603
604ChrIn:
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
624jgl1: cmp ax,7200h ; CTRL-PRTSC ?
625 jnz sja0
626 mov al,10h ; yes, make it a ctrl-P
627sja0: or al,al ; special case?
628 jnz KeyRet
629 mov [AltAH],ah
630KeyRet:
631 ret
632
633
634subttl $ConRdnd - Console non-destructive Input, no wait
635page
636
637;------------------------------------------------------------------------
638; Console non-destructive Input, no wait
639;
640; entry:
641; DS:BX = pointer to Request packet
642;
643
644assume 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
652sjq0:
653 DEBUG 10h,1,<CNDR:$x=$x? >,<dx,CurrSc>
654 cmp dx,[CurrSc]
655IFDEF DEBUGFLG
656 je sjq1
657 jmp ConBus
658ELSE
659 jne ConBus ; not current screen, no char avail
660ENDIF
661; call GetSIBAdr ; get pointer to the SIB
662; call DoPBlock ; block the process
663; jmp short sjq0 ; test flag again
664sjq1:
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
679NotBk:
680 cmp ax,7200h ; CTRL-PRTSC ?
681 jnz rdExit
682 mov al,10h ; yes, make it a ctrl-P
683rdExit:
684 mov byte ptr ds:[bx].MEDIA,al ; save character
685DoExit: jmp StatusComplete
686
687ConBus: DEBUG 10h,1,< ConBus - >,<>
688 jmp StatusDevReady
689
690
691subttl $ConFlsh - Console Flush Input
692page
693
694;------------------------------------------------------------------------
695; Console Flush Input
696;
697; entry:
698; DS:BX = pointer to Request packet
699;
700
701assume 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
709sjr0:
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
715sjr1:
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
731subttl $ConWrit - Console Output (Write)
732page
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
743assume 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
752sjb0: push cs
753 pop ds
754 assume ds:Code
755 mov bx,[CurrSIB]
756
757ConWLoop:
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
761sjb1: call DoPBlock ; block the process
762 jmp short ConWLoop ; test ALL flags again
763sjb2:
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
768sjb3:
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...
773sjb4:
774 mov al,es:[di] ; get a character
775 inc di
776 call CharOut
777 loop ConWLoop
778CWExit: jmp StatusComplete
779
780
781subttl CharOut - Output a character to the screen
782page
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
794assume ds:NOTHING,es:NOTHING
795
796IF ANSI
797 include ansi.inc
798ELSE
799CharOut:
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
808ENDIF
809
810
811subttl $GenIOCTL - Generic IOCTL
812page
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
823FunCode = 14 ; Function Code
824FunCat = 13 ; Function Category
825;***
826RegSI = 15 ; Contents of SI
827RegDI = 17 ; Contents of DI
828DatBuf = 19 ; Pointer to data buffer
829
830;--- Code & Category definitions
831IOC_SC = 03h ;--- Screen Control
832IOSC_LS = 41h ; Locate SIB
833IOSC_SS = 42h ; save segment
834IOSC_RS = 43h ; restore segment
835IOSC_EI = 44h ; re-enable i/o
836IOSC_IS = 45h ; initialize screen
837
838assume 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
848sjc0: cmp al,IOSC_SS
849 jne sjc1
850 jmp short do_IOSC_SS
851sjc1: cmp al,IOSC_RS
852 jne sjc2
853 jmp do_IOSC_RS
854sjc2: cmp al,IOSC_EI
855 jne sjc3
856 jmp do_IOSC_EI
857sjc3: cmp al,IOSC_IS
858 jne GI_BadCode
859 jmp do_IOSC_IS
860
861GI_BadCode:
862 jmp CmdErr ; error exit: Command error
863
864
865subttl do_IOSC_LS - Locate SIB
866page
867
868;------------------------------------------------------------------------
869; Locate SIB
870;
871; entry:
872; SI = SIB Number
873; DS:BX = pointer to Request packet
874;
875
876assume ds:NOTHING,es:NOTHING
877
878do_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
894CurrLS:
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
904IF EAGLE
905 mov al,es:[CRT_MODE]
906 xor ah,ah
907 mov si,ax
908 mov ah,ScreenLen[si]
909 xor al,al
910ELSE
911 mov ax,es:[CRT_LEN]
912 assume es:NOTHING ; not true, but just to be safe
913ENDIF
914 mov [bx].SizeNeeded,ax ; save size of segment
915 mov ax,dx ; pointer to current SIB
916retLS:
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
925BadNum:
926 mov word ptr ds:[bx].RegSI,1 ; bad SIB number error
927 jmp StatusComplete
928
929
930subttl do_IOSC_SS - Save Segment
931page
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
941assume ds:NOTHING,es:NOTHING
942
943do_IOSC_SS:
944 cmp si,(MaxSeg-1) ; within range?
945BadNumJ1:
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
965IF 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
972ENDIF
973 pop si ; restore segment index
974;--- save a segment of screen data
975nfSS:
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
993do_save:
994IF 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
1000ENDIF
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
1006IF BLANK
1007 or al,8
1008 out dx,al ; turn on video
1009ENDIF
1010 pop ds
1011 pop bx
1012 mov word ptr ds:[bx].RegSI,0 ; operation ok
1013 jmp StatusComplete
1014
1015
1016subttl do_IOSC_RS - Restore Segment
1017page
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
1027assume ds:NOTHING,es:NOTHING
1028
1029do_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
1051IF 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
1061ENDIF
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
1069sjd0:
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
1089nfRS:
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
1104do_rest:
1105IF 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
1111ENDIF
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
1117IF BLANK
1118 or al,8
1119 out dx,al ; turn on video
1120ENDIF
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
1128BadNumJ:
1129 jmp BadNum
1130
1131
1132subttl do_IOSC_EI - Re-enable i/o
1133page
1134
1135;------------------------------------------------------------------------
1136; Re-enable i/o
1137;
1138; entry:
1139; DS:BX = pointer to Request packet
1140;
1141
1142assume ds:NOTHING,es:NOTHING
1143
1144do_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
1154subttl do_IOSC_IS - Initialize Screen
1155page
1156
1157;------------------------------------------------------------------------
1158; Initialize Screen
1159;
1160; entry:
1161; SI = SIB Number
1162; DS:BX = pointer to Request packet
1163;
1164
1165assume ds:NOTHING,es:NOTHING
1166
1167do_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
1189subttl $ConStop - Stop (freeze) console output
1190page
1191
1192;------------------------------------------------------------------------
1193; Stop (freeze) console output
1194;
1195
1196assume 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
1204subttl $ConStart - Start (continue) console output
1205page
1206
1207;------------------------------------------------------------------------
1208; Start (continue) console output
1209;
1210
1211assume 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
1220csRet: jmp StatusComplete
1221
1222
1223subttl DoPBlock - Block the current process
1224page
1225
1226;------------------------------------------------------------------------
1227; Block the current process
1228;
1229; entry:
1230; CS:AX = address to block on
1231;
1232; modifies: AX, FLAGS
1233;
1234
1235assume ds:NOTHING,es:NOTHING
1236
1237DoPBlock:
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
1255subttl DoPRun - Restart a process
1256page
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
1267assume ds:NOTHING,es:NOTHING
1268
1269DoPRun:
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
1283subttl GetSIBAdr - Return SIB address
1284page
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
1298assume ds:Code,es:NOTHING
1299
1300GetSIBAdr:
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
1310subttl GetSegAdr - Return segment address
1311page
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
1324assume ds:Code,es:NOTHING
1325
1326GetSegAdr:
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
1336ifdef DEBUGFLG
1337if NOT INBIOS
1338 INCLUDE BUGCODE.INC
1339endif
1340endif
1341
1342
1343subttl $ConInit - Initialization Routine
1344page
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
1354assume ds:NOTHING,es:NOTHING
1355
1356$ConInit:
1357IF 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
1367ENDIF
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
1411IF INBIOS
1412Code ends
1413
1414BiosInit segment para public 'CODE'
1415ENDIF
1416
1417Intro 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
1422BiosInit ends
1423
1424 END
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.OBJ
new file mode 100644
index 0000000..ed4dc74
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/IBMMTCON.OBJ
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/READ_ME b/v4.0-ozzie/bin/DISK2/BIOS/READ_ME
new file mode 100644
index 0000000..03623a4
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/READ_ME
@@ -0,0 +1,25 @@
129 May 1984
2
3The object files given here are sufficient to create the BIOS
4for the IBM system. Some sources are given as examples for
5OEM supplied device drivers. These sources do not necessarily
6implement all the features described in the device driver
7documentation. They have evolved in parallel with the
8documentation, so some features described in the documentation
9may not yet be present in the drivers. Below is a summary of
10the files supplied:
11
12 read_me This file.
13 ibmbio.asm Main body of the BIOS.
14 ibmdsk.asm Floppy and Hard disk drivers.
15 ibmmtcon.asm Multi-screen console driver.
16 ansi.inc ANSI X3.64 terminal emulation.
17 bugcode.inc Module which implements debugging
18 prints. The routine PUTC must be
19 modified for other devices. See
20 also the file DEFDBUG.INC.
21 sys*.obj The SYSINIT program. No source supplied.
22 biosobj.mak Contains instructions for building the
23 IBM BIOS.
24 bootpach.exe Modifies a V2.0 boot sector (on A:) for
25 the IBM to accomodate the larger BIOS.
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/SYSIMES.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/SYSIMES.OBJ
new file mode 100644
index 0000000..4439f35
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/SYSIMES.OBJ
Binary files differ
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/SYSINI.OBJ b/v4.0-ozzie/bin/DISK2/BIOS/SYSINI.OBJ
new file mode 100644
index 0000000..0fc06ba
--- /dev/null
+++ b/v4.0-ozzie/bin/DISK2/BIOS/SYSINI.OBJ
Binary files differ
diff --git a/v4.0-ozzie/bin/DRDOS1.IMD b/v4.0-ozzie/bin/DRDOS1.IMD
new file mode 100644
index 0000000..0a7a84f
--- /dev/null
+++ b/v4.0-ozzie/bin/DRDOS1.IMD
Binary files differ
diff --git a/v4.0-ozzie/bin/DRDOS1_IMD.img b/v4.0-ozzie/bin/DRDOS1_IMD.img
new file mode 100644
index 0000000..d6d7165
--- /dev/null
+++ b/v4.0-ozzie/bin/DRDOS1_IMD.img
Binary files differ
diff --git a/v4.0-ozzie/bin/DRDOS2.IMD b/v4.0-ozzie/bin/DRDOS2.IMD
new file mode 100644
index 0000000..972058b
--- /dev/null
+++ b/v4.0-ozzie/bin/DRDOS2.IMD
Binary files differ
diff --git a/v4.0-ozzie/bin/DRDOS2_IMD.img b/v4.0-ozzie/bin/DRDOS2_IMD.img
new file mode 100644
index 0000000..64d8395
--- /dev/null
+++ b/v4.0-ozzie/bin/DRDOS2_IMD.img
Binary files differ