diff options
Diffstat (limited to 'v4.0-ozzie')
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 @@ | |||
| 1 | date | ||
| 2 | time | ||
| 3 | prompt $p$g | ||
| 4 | path 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 @@ | |||
| 1 | cd bin | ||
| 2 | pound 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 @@ | |||
| 1 | c: | ||
| 2 | cd \bin | ||
| 3 | pound 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 @@ | |||
| 1 | c: | ||
| 2 | cd \bin | ||
| 3 | cd a:\bin | ||
| 4 | detach pound 800 bbset.exe sm.exe | ||
| 5 | detach pound 290 a:bbset.exe a:sm.exe | ||
| 6 | basica 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 @@ | |||
| 1 | buffers = 40 | ||
| 2 | files = 20 | ||
| 3 | break=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 @@ | |||
| 1 | define F7 a:\command.com a:\ | ||
| 2 | define 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 | |||
| 11 | CMDTABL 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 | ||
| 48 | GRMODE 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) | ||
| 73 | SRMODE 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 | |||
| 78 | PAGE | ||
| 79 | ; The following are duplicates of the same variables from the ROM | ||
| 80 | ; | ||
| 81 | ;* WARNING - the following two variables are accessed as a word | ||
| 82 | MODE DB 3 | ||
| 83 | MAXCOL DB 79 | ||
| 84 | IF LINE25 ; special treatment of line 25? | ||
| 85 | maxrow equ 24 | ||
| 86 | ELSE | ||
| 87 | maxrow equ 25 | ||
| 88 | ENDIF | ||
| 89 | ;* WARNING - the following two variables are accessed as a word | ||
| 90 | COL DB 0 ; current column | ||
| 91 | ROW DB 0 ; current row | ||
| 92 | |||
| 93 | |||
| 94 | AnsiState LABEL BYTE ; the following must be saved on a screen swap | ||
| 95 | WRAP DB 1 ; 0 = NO WRAP, 1 = WRAP | ||
| 96 | EnaL25 DB 0 ; 0 = 25th line disabled, 1 = enabled | ||
| 97 | STATE DW S1 | ||
| 98 | SAVCR DW 0 ; saved cursor position | ||
| 99 | ;* WARNING - the following two variables are accessed as a word | ||
| 100 | SelChar DB 0 ; <,=,> or ? private use indicators | ||
| 101 | PRMCNT LABEL BYTE ; number of parameters for command | ||
| 102 | PRMCNTW DW 0 | ||
| 103 | NUMPARAM equ 5 ; max. number of parameters | ||
| 104 | PARAM DB NUMPARAM DUP (?) ; buffer for command parameters | ||
| 105 | ;* WARNING - the following two variables are accessed as a word | ||
| 106 | attrw LABEL WORD | ||
| 107 | ATTR DB 00000111B ;CHARACTER ATTRIBUTE | ||
| 108 | BPAGE DB 0 ;BASE PAGE | ||
| 109 | |||
| 110 | AnsiSize equ ($-AnsiState) | ||
| 111 | |||
| 112 | IF (AnsiSize GT TermSize) | ||
| 113 | .RADIX 0 ; ERROR - Terminal state not big enough | ||
| 114 | ENDIF | ||
| 115 | |||
| 116 | ;------------------------------------------------------------- | ||
| 117 | ; | ||
| 118 | ; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE | ||
| 119 | ; | ||
| 120 | base dw 0b800h | ||
| 121 | screen_seg dw 00000h | ||
| 122 | |||
| 123 | chrout: cmp al,13 ; carriage return? | ||
| 124 | ja outchr | ||
| 125 | jnz trylf | ||
| 126 | mov [col],0 | ||
| 127 | ;; jmp short setit | ||
| 128 | jmp setit | ||
| 129 | |||
| 130 | trylf: cmp al,10 ; line feed? | ||
| 131 | jz lf | ||
| 132 | cmp al,7 ; bell? | ||
| 133 | jnz trytab | ||
| 134 | torom: | ||
| 135 | mov bx,[attrw] | ||
| 136 | and bl,7 | ||
| 137 | mov ah,14 | ||
| 138 | int 10h | ||
| 139 | ret5: ret | ||
| 140 | |||
| 141 | trytab: | ||
| 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] | ||
| 152 | tunder: | ||
| 153 | mov [col],al | ||
| 154 | jmp short setit | ||
| 155 | |||
| 156 | tryback: | ||
| 157 | cmp al,8 ; backspace? | ||
| 158 | jnz outchr | ||
| 159 | cmp [col],0 | ||
| 160 | jz ret5 | ||
| 161 | dec [col] | ||
| 162 | jmp short setit | ||
| 163 | |||
| 164 | outchr: | ||
| 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 | ||
| 177 | outchr1: | ||
| 178 | mov [col],0 | ||
| 179 | lf: 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 | ||
| 184 | lf1: call scroll | ||
| 185 | |||
| 186 | setit: mov dx,word ptr col | ||
| 187 | mov bh,[bpage] | ||
| 188 | mov ah,2 | ||
| 189 | int 10h | ||
| 190 | ret | ||
| 191 | |||
| 192 | scroll: mov al,mode | ||
| 193 | cmp al,2 | ||
| 194 | jz myscroll | ||
| 195 | cmp al,3 | ||
| 196 | jz myscroll | ||
| 197 | IF 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 | ||
| 205 | ELSE | ||
| 206 | mov al,10 | ||
| 207 | jmp torom | ||
| 208 | ENDIF | ||
| 209 | myscroll: | ||
| 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 | ||
| 235 | wait2: 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 | ||
| 248 | sret: push cs | ||
| 249 | pop ds | ||
| 250 | ret | ||
| 251 | |||
| 252 | |||
| 253 | CharOut: 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 | ||
| 272 | NOT_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 | ; | ||
| 303 | VIDEO: MOV SI,OFFSET STATE | ||
| 304 | JMP [SI] | ||
| 305 | |||
| 306 | S2: CMP AL,'[' | ||
| 307 | JZ S22 | ||
| 308 | JMP S1 | ||
| 309 | S22: 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 | |||
| 315 | S30: 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 | |||
| 322 | S3: CMP AL,';' | ||
| 323 | JNZ S3C | ||
| 324 | S3A: INC PRMCNT | ||
| 325 | S3B: CALL GETPTR | ||
| 326 | XOR AX,AX | ||
| 327 | MOV WORD PTR [BX],AX ;DEFAULT VALUE IS ZERO | ||
| 328 | RET | ||
| 329 | |||
| 330 | S3C: 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 | |||
| 342 | S3D: | ||
| 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 | ||
| 349 | S3RET: 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 | |||
| 369 | S7: MOV BX,OFFSET CMDTABL-3 | ||
| 370 | ; | ||
| 371 | S7A: ADD BX,3 | ||
| 372 | CMP BYTE PTR [BX],0 | ||
| 373 | JZ S1B | ||
| 374 | CMP BYTE PTR [BX],AL | ||
| 375 | JNZ S7A | ||
| 376 | ; | ||
| 377 | S7B: 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 | ||
| 385 | S7C: JMP AX ;AL = COMMAND | ||
| 386 | |||
| 387 | S1: CMP AL,1Bh ;ESCAPE SEQUENCE? | ||
| 388 | JNZ S1B | ||
| 389 | MOV WORD PTR [SI],OFFSET S2 | ||
| 390 | RET | ||
| 391 | |||
| 392 | S1B: CALL CHROUT | ||
| 393 | S1A: MOV WORD PTR [STATE],OFFSET S1 | ||
| 394 | RET | ||
| 395 | |||
| 396 | MOVCUR: CMP BYTE PTR [BX],AH | ||
| 397 | JZ SETCUR | ||
| 398 | ADD BYTE PTR [BX],AL | ||
| 399 | LOOP MOVCUR | ||
| 400 | SETCUR: MOV DX,WORD PTR COL | ||
| 401 | XOR BX,BX | ||
| 402 | MOV AH,2 | ||
| 403 | int 10h ; call ROM | ||
| 404 | JMP S1A | ||
| 405 | |||
| 406 | HVP: | ||
| 407 | CUP: | ||
| 408 | IF 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 | ||
| 414 | cup3: | ||
| 415 | ELSE | ||
| 416 | CMP CL,maxrow | ||
| 417 | JA SETCUR | ||
| 418 | ENDIF | ||
| 419 | MOV AL,MAXCOL | ||
| 420 | MOV CH,BYTE PTR [BX+1] | ||
| 421 | OR CH,CH | ||
| 422 | JZ CUP1 | ||
| 423 | DEC CH | ||
| 424 | CUP1: CMP AL,CH | ||
| 425 | JA CUP2 | ||
| 426 | MOV CH,AL | ||
| 427 | CUP2: XCHG CL,CH | ||
| 428 | DEC CH | ||
| 429 | MOV WORD PTR COL,CX | ||
| 430 | JMP SETCUR | ||
| 431 | |||
| 432 | CUF: MOV AH,MAXCOL | ||
| 433 | MOV AL,1 | ||
| 434 | CUF1: MOV BX,OFFSET COL | ||
| 435 | JMP MOVCUR | ||
| 436 | |||
| 437 | CUB: MOV AX,00FFH | ||
| 438 | JMP CUF1 | ||
| 439 | |||
| 440 | CUU: MOV AX,00FFH | ||
| 441 | CUU1: MOV BX,OFFSET ROW | ||
| 442 | JMP MOVCUR | ||
| 443 | |||
| 444 | CUD: MOV AX,(maxrow-1)*256+1 | ||
| 445 | IF LINE25 | ||
| 446 | cmp ah,[row] ; at bottom of screen? | ||
| 447 | ja SETCUR | ||
| 448 | ENDIF | ||
| 449 | JMP CUU1 | ||
| 450 | |||
| 451 | SCP: MOV AX,WORD PTR COL | ||
| 452 | MOV SAVCR,AX | ||
| 453 | JMP SETCUR | ||
| 454 | |||
| 455 | RCP: MOV AX,SAVCR | ||
| 456 | IF LINE25 | ||
| 457 | cmp ch,maxrow | ||
| 458 | jb rcp1 | ||
| 459 | cmp EnaL25,0 | ||
| 460 | jz rcp2 | ||
| 461 | ENDIF | ||
| 462 | rcp1: MOV WORD PTR COL,AX | ||
| 463 | rcp2: JMP SETCUR | ||
| 464 | |||
| 465 | SGR: XOR CX,CX | ||
| 466 | XCHG CL,PRMCNT | ||
| 467 | CALL GETPTR | ||
| 468 | INC CX | ||
| 469 | SGR1: MOV AL,BYTE PTR [BX] | ||
| 470 | PUSH BX | ||
| 471 | MOV BX,OFFSET GRMODE | ||
| 472 | SGR2: 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 | ||
| 481 | SGR3: POP BX | ||
| 482 | INC BX | ||
| 483 | LOOP SGR1 | ||
| 484 | JMP SETCUR | ||
| 485 | |||
| 486 | ED: | ||
| 487 | IF LINE25 | ||
| 488 | cmp row,maxrow ; on 25th line? | ||
| 489 | je EL ; yes, treat like Erase in Line | ||
| 490 | ENDIF | ||
| 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 | ||
| 501 | ed1: mov ch,row ; to end | ||
| 502 | inc ch | ||
| 503 | cmp ch,dh | ||
| 504 | jae EL | ||
| 505 | ed2: mov bh,attr | ||
| 506 | MOV AX,0600H | ||
| 507 | int 10h ; call ROM | ||
| 508 | |||
| 509 | EL: 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 | ||
| 516 | el1: test al,2 ; to beginning? | ||
| 517 | je el2 | ||
| 518 | mov cl,0 | ||
| 519 | el2: mov bh,attr | ||
| 520 | mov ax,0600H | ||
| 521 | int 10h | ||
| 522 | S1A_j: jmp S1A | ||
| 523 | |||
| 524 | IL: mov ah,7 ; scroll down | ||
| 525 | jmp short dl1 | ||
| 526 | |||
| 527 | xDL: mov ah,6 ; scroll up | ||
| 528 | dl1: 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 | |||
| 537 | RM: XOR CL,CL | ||
| 538 | JMP SHORT SM1 | ||
| 539 | |||
| 540 | SM: MOV CL,1 | ||
| 541 | SM1: 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 | |||
| 562 | SM2: MOV AH,0 | ||
| 563 | int 10h ; call ROM | ||
| 564 | JMP S1A_j | ||
| 565 | |||
| 566 | ; GetPtr - get a pointer to the current parameter | ||
| 567 | GETPTR: MOV BX,PRMCNTW | ||
| 568 | CMP BX,NUMPARAM | ||
| 569 | JB GET1 | ||
| 570 | DEC PRMCNT | ||
| 571 | JMP GETPTR | ||
| 572 | GET1: 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 @@ | |||
| 1 | ibmbio.obj: ibmbio.asm defdbug.inc bugcode.inc | ||
| 2 | masm ibmbio; | ||
| 3 | |||
| 4 | ibmmtcon.obj: ibmmtcon.asm ansi.inc defdbug.inc | ||
| 5 | masm ibmmtcon; | ||
| 6 | |||
| 7 | ibmdsk.obj: ibmdsk.asm defdbug.inc | ||
| 8 | masm ibmdsk; | ||
| 9 | |||
| 10 | sysini.obj: sysini.asm dossym.inc devsym.inc syscalls.inc | ||
| 11 | masm sysini; | ||
| 12 | |||
| 13 | sysimes.obj: sysimes.asm | ||
| 14 | masm sysimes; | ||
| 15 | |||
| 16 | ibmbio.exe: ibmbio.obj ibmmtcon.obj ibmdsk.obj sysini.obj sysimes.obj | ||
| 17 | link ibmbio ibmmtcon ibmdsk sysini sysimes,ibmbio,ibmbio/map; | ||
| 18 | |||
| 19 | ibmbio.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 | |||
| 8 | IFDEF 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 | ||
| 93 | DPRINTF 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 | |||
| 118 | dpf1: 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 | |||
| 140 | dpf1$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 | ||
| 147 | dpf2: call putchar | ||
| 148 | jmp dpf1 | ||
| 149 | |||
| 150 | ; have the end of the format string - exit | ||
| 151 | |||
| 152 | dpf3: 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 | |||
| 170 | dpf4: 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 | ||
| 180 | dpf5: 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 | |||
| 189 | dpfd1: 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 | |||
| 198 | dpfc1: 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 | |||
| 207 | dpfb1: 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 | |||
| 216 | dpfs1: 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 | ||
| 223 | SSB: 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 | |||
| 239 | dpfs2: 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 | ||
| 245 | dpfs3: jmp dpf1 | ||
| 246 | |||
| 247 | dpfbb1: cmp al,'B' | ||
| 248 | je dpfbb2 ; is 'B' format | ||
| 249 | |||
| 250 | ; error in format code - print message | ||
| 251 | |||
| 252 | dpferr: push cs | ||
| 253 | pop es | ||
| 254 | mov di,OFFSET dpfa ; (es:di) = error message | ||
| 255 | sub cx,cx | ||
| 256 | jmp dpfs2 | ||
| 257 | |||
| 258 | dpfa: DB '%% BAD FMT %%',0 | ||
| 259 | |||
| 260 | ; have B format | ||
| 261 | |||
| 262 | dpfbb2: 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 | ||
| 268 | dpfbb3: 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 | |||
| 276 | DPRINTF 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 | |||
| 287 | THBA DB '0123456789abcdef' | ||
| 288 | |||
| 289 | PUBLIC THB | ||
| 290 | THB 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 | |||
| 310 | THB 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 | ||
| 324 | THW PROC near | ||
| 325 | |||
| 326 | push ax | ||
| 327 | xchg ah,al | ||
| 328 | call THB | ||
| 329 | pop ax | ||
| 330 | call THB | ||
| 331 | ret | ||
| 332 | |||
| 333 | THW 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 | ||
| 348 | TDW 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 | |||
| 358 | TDW 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 | |||
| 370 | tdw$ 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 | ||
| 379 | tdw$1: xchg ax,dx | ||
| 380 | add al,'0' | ||
| 381 | call putchar | ||
| 382 | ret | ||
| 383 | |||
| 384 | TDW$ 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 | ||
| 402 | ATOD 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 | |||
| 421 | atod1: 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 | |||
| 441 | atod7: clc | ||
| 442 | |||
| 443 | ; Done with number, error | ||
| 444 | ; 'C' set | ||
| 445 | |||
| 446 | atod8: dec si ; backup over non-decimal (or error) char | ||
| 447 | atod9: pop cx | ||
| 448 | xchg ax,dx ; (ax) = number iff no error | ||
| 449 | pop dx ; restore registers | ||
| 450 | ret ; exit | ||
| 451 | |||
| 452 | ATOD ENDP | ||
| 453 | |||
| 454 | ;** putchar - put a character on the console | ||
| 455 | ; | ||
| 456 | ; ENTRY (al) = character | ||
| 457 | ; EXIT none | ||
| 458 | ; USES ax,flags | ||
| 459 | |||
| 460 | |||
| 461 | UR_DAT = 02f8H ; COM1 = 03f8H, COM2 = 02f8H | ||
| 462 | UR_IEN = UR_DAT+1 ; Interrupt enable | ||
| 463 | UR_IER = UR_DAT+2 ; interrupt ID | ||
| 464 | UR_LCR = UR_DAT+3 ; line control registers | ||
| 465 | UR_MCR = UR_DAT+4 ; modem control register | ||
| 466 | UR_LSR = UR_DAT+5 ; line status register | ||
| 467 | UR_MSR = UR_DAT+6 ; modem status regiser | ||
| 468 | UR_DLL = UR_DAT ; divisor latch least sig | ||
| 469 | UR_DLM = UR_DAT+1 ; divisor latch most sig | ||
| 470 | |||
| 471 | iflag 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 | |||
| 479 | inchr: 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 | ||
| 486 | inchr1: ret | ||
| 487 | |||
| 488 | |||
| 489 | PUBLIC putchar | ||
| 490 | putchar 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 | |||
| 518 | putc1: 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 | |||
| 527 | putc2: call inchr | ||
| 528 | jz putc2 | ||
| 529 | cmp al,17 | ||
| 530 | jnz putc2 | ||
| 531 | |||
| 532 | putc3: popf | ||
| 533 | mov dx,UR_LSR | ||
| 534 | putc4: 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 | |||
| 551 | putchar ENDP | ||
| 552 | |||
| 553 | ENDIF | ||
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 | |||
| 10 | DEBUG 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 | ||
| 20 | c: 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 | ||
| 48 | b: popf | ||
| 49 | ENDIF | ||
| 50 | ENDM | ||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | |||
| 55 | ;** ERRNZ - generate assembly error if arg != 0 | ||
| 56 | ; | ||
| 57 | |||
| 58 | ERRNZ 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 | |||
| 71 | DBBEG 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 | ||
| 78 | lab: | ||
| 79 | ENDM | ||
| 80 | |||
| 81 | |||
| 82 | |||
| 83 | DBJMP 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 | |||
| 104 | DEBUGTST MACRO N,M | ||
| 105 | LOCAL A | ||
| 106 | test BYTE PTR BUGBITS,n | ||
| 107 | jz A | ||
| 108 | test BYTE PTR BUGBITS+1,m | ||
| 109 | A: | ||
| 110 | ENDM | ||
| 111 | |||
| 112 | DBEND MACRO | ||
| 113 | DBLAB %DBCNT | ||
| 114 | DBCNT = DBCNT+1 | ||
| 115 | popf | ||
| 116 | ENDM | ||
| 117 | |||
| 118 | DBLAB MACRO N | ||
| 119 | DBLAB&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 @@ | |||
| 1 | TITLE 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 | ||
| 18 | CONSFLAG = 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 | |||
| 40 | SCHEDCOUNT EQU 50 ; # msec/scheduler tick | ||
| 41 | MOTORCOUNT 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 | |||
| 50 | BiosSeg GROUP Code,BiosInit | ||
| 51 | Code SEGMENT BYTE PUBLIC 'CODE' | ||
| 52 | |||
| 53 | ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING | ||
| 54 | |||
| 55 | START$: | ||
| 56 | JMP INIT | ||
| 57 | |||
| 58 | DB 20 DUP (0) ; IBM WANTS SOME ZEROED AREA | ||
| 59 | |||
| 60 | SUBTTL Jump tables for devices | ||
| 61 | ;-------------------------------------------------------------- | ||
| 62 | ; | ||
| 63 | ; COMMAND JUMP TABLES | ||
| 64 | ; | ||
| 65 | ; BEWARE - These tables overlap somewhat! -c.p. | ||
| 66 | ; | ||
| 67 | IF CONSFLAG | ||
| 68 | CONTBL: | ||
| 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 | ||
| 91 | ENDIF ;CONSFLAG | ||
| 92 | |||
| 93 | AUXTBL: | ||
| 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 | |||
| 117 | TIMTBL: | ||
| 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 | |||
| 129 | PRNTBL: | ||
| 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 | |||
| 153 | SUBTTL Device entry points | ||
| 154 | ;--------------------------------------------------- | ||
| 155 | ; | ||
| 156 | ; Device Entry point | ||
| 157 | ; | ||
| 158 | CMDLEN = 0 ;LENGTH OF THIS COMMAND | ||
| 159 | UNIT = 1 ;SUB UNIT SPECIFIER | ||
| 160 | CMD = 2 ;COMMAND CODE | ||
| 161 | STATUS = 3 ;STATUS | ||
| 162 | MEDIA = 13 ;MEDIA DESCRIPTOR | ||
| 163 | TRANS = 14 ;TRANSFER ADDRESS | ||
| 164 | Dfun = DWORD PTR 14 ; Passed addr of dos function | ||
| 165 | COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS | ||
| 166 | START = 20 ;FIRST BLOCK TO TRANSFER | ||
| 167 | |||
| 168 | AUXNUM DB 0 ;WHICH AUX DEVICE WAS REQUESTED | ||
| 169 | |||
| 170 | ; Dos routine to do functions for device drivers | ||
| 171 | PUBLIC DosFunction | ||
| 172 | DosFunction DD 0 ; Device help function entry point | ||
| 173 | ScrnIOok dd 0 ; (char *) true if in current screen locus | ||
| 174 | |||
| 175 | TIM_DRV DB -1 ; TIME WHEN LAST DISK I/O PERFORMED | ||
| 176 | TIM_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 | ||
| 198 | BUGBITS DB 000H ; group bits | ||
| 199 | DB 0ffH ; level bits | ||
| 200 | |||
| 201 | Strategy PROC FAR | ||
| 202 | RET | ||
| 203 | Strategy ENDP | ||
| 204 | |||
| 205 | IF CONSFLAG | ||
| 206 | CON$IN: | ||
| 207 | PUSH SI | ||
| 208 | MOV SI,OFFSET CONTBL | ||
| 209 | JMP SHORT Interrupt | ||
| 210 | ENDIF ;CONSFLAG | ||
| 211 | |||
| 212 | AUX0$IN: | ||
| 213 | PUSH SI | ||
| 214 | PUSH AX | ||
| 215 | XOR AL,AL | ||
| 216 | JMP SHORT AUXENT | ||
| 217 | |||
| 218 | AUX1$IN: | ||
| 219 | PUSH SI | ||
| 220 | PUSH AX | ||
| 221 | MOV AL,1 | ||
| 222 | AUXENT: | ||
| 223 | MOV SI,OFFSET AUXTBL | ||
| 224 | JMP SHORT entry1 | ||
| 225 | |||
| 226 | PRN0$IN: | ||
| 227 | PUSH SI | ||
| 228 | PUSH AX | ||
| 229 | XOR AL,AL | ||
| 230 | JMP SHORT PRNENT | ||
| 231 | |||
| 232 | PRN1$IN: | ||
| 233 | PUSH SI | ||
| 234 | PUSH AX | ||
| 235 | MOV AL,1 | ||
| 236 | JMP SHORT PRNENT | ||
| 237 | |||
| 238 | PRN2$IN: | ||
| 239 | PUSH SI | ||
| 240 | PUSH AX | ||
| 241 | MOV AL,2 | ||
| 242 | PRNENT: | ||
| 243 | MOV SI,OFFSET PRNTBL | ||
| 244 | JMP SHORT entry1 | ||
| 245 | |||
| 246 | TIM$IN: | ||
| 247 | PUSH SI | ||
| 248 | MOV SI,OFFSET TIMTBL | ||
| 249 | |||
| 250 | |||
| 251 | COMMENT * | ||
| 252 | Interrupt is the main part of the interrupt device entry point( a | ||
| 253 | misnomer, actually is the execute function entry ) for all devices. | ||
| 254 | The various devices set up the dispatch table address and unit choice | ||
| 255 | and then jump to Interrupt which then dispatches to the appropriate | ||
| 256 | device routine. | ||
| 257 | |||
| 258 | Entry 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 | |||
| 263 | Exit 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 | ||
| 274 | Interrupt PROC FAR | ||
| 275 | PUSH AX | ||
| 276 | entry1: | ||
| 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 | ||
| 302 | Interrupt ENDP | ||
| 303 | |||
| 304 | SUBTTL Routines used by device routines | ||
| 305 | COMMENT * | ||
| 306 | All routines on this page are various exits for device functions. | ||
| 307 | They each return different information in the request packet for the | ||
| 308 | dos. 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 | |||
| 340 | Entry 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 | |||
| 345 | Exit parameters: | ||
| 346 | ES:BX Pointer to packet | ||
| 347 | AX Destroyed | ||
| 348 | SI Destroyed | ||
| 349 | All other registers preserved | ||
| 350 | * | ||
| 351 | |||
| 352 | PUBLIC StatusDevReady | ||
| 353 | StatusDevReady PROC NEAR ; Device has data or can send | ||
| 354 | MOV AH,00000011B ; Done + busy | ||
| 355 | JMP SHORT SetStatus | ||
| 356 | StatusDevReady ENDP | ||
| 357 | |||
| 358 | PUBLIC CmdErr | ||
| 359 | CmdErr PROC NEAR ; Bad device command number | ||
| 360 | debug 1,4,< CMDERR - $b $x\n>,<ax,si> | ||
| 361 | MOV AL,3 ; Unknown command error | ||
| 362 | CmdErr ENDP | ||
| 363 | |||
| 364 | StatusPartialXfer PROC NEAR | ||
| 365 | SUB [BX].COUNT,CX ;# of successful I/O's | ||
| 366 | StatusPartialXfer ENDP | ||
| 367 | |||
| 368 | PUBLIC StatusError | ||
| 369 | StatusError PROC NEAR | ||
| 370 | MOV AH,10000001B ; Error + done | ||
| 371 | JMP SHORT SetStatus | ||
| 372 | StatusError ENDP | ||
| 373 | |||
| 374 | StatusNoXfer PROC NEAR | ||
| 375 | XOR AX,AX | ||
| 376 | MOV [BX].COUNT,AX ; No chars read | ||
| 377 | StatusNoXfer ENDP | ||
| 378 | |||
| 379 | PUBLIC StatusComplete | ||
| 380 | StatusComplete PROC NEAR | ||
| 381 | MOV AH,00000001B ; Done | ||
| 382 | PUBLIC SetStatus | ||
| 383 | SetStatus: | ||
| 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 | ||
| 394 | XXX PROC FAR | ||
| 395 | RET ;RESTORE REGS AND RETURN | ||
| 396 | XXX ENDP | ||
| 397 | StatusComplete ENDP | ||
| 398 | |||
| 399 | StatusWait 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 | ||
| 404 | StatusWait ENDP | ||
| 405 | |||
| 406 | IF CONSFLAG | ||
| 407 | ; Set the address of the dos function routine for drivers | ||
| 408 | SetAddr 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 | ||
| 420 | SetAddr ENDP | ||
| 421 | |||
| 422 | |||
| 423 | ;------------------------------------------------------------- | ||
| 424 | ; | ||
| 425 | ; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE | ||
| 426 | ; | ||
| 427 | ; CALLED VIA INT 29H | ||
| 428 | ; | ||
| 429 | CHROUT = 29H | ||
| 430 | |||
| 431 | OUTCHR: 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 | ||
| 438 | ENDIF ;CONSFLAG | ||
| 439 | |||
| 440 | ;---------------------------------------------- | ||
| 441 | ; | ||
| 442 | ; SET DX TO AUXNUM | ||
| 443 | ; | ||
| 444 | GETDX: MOV DL,[AUXNUM] | ||
| 445 | XOR DH,DH | ||
| 446 | RET | ||
| 447 | |||
| 448 | SUBTTL Console driver | ||
| 449 | COMMENT * | ||
| 450 | This is the console( CON ) device driver. The input side is assigned | ||
| 451 | to the keyboard and the output to the video screen. The output code | ||
| 452 | remains more or less the same as in 2.0. The input side, however, is | ||
| 453 | changed for 4.0 to enter an I/O wait rather than loop waiting for a | ||
| 454 | character. | ||
| 455 | * | ||
| 456 | |||
| 457 | IF CONSFLAG | ||
| 458 | CONDEV 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 ' | ||
| 464 | ELSE | ||
| 465 | EXTRN CONDEV:NEAR | ||
| 466 | PUBLIC AUXDEV | ||
| 467 | ENDIF ;CONSFLAG | ||
| 468 | |||
| 469 | IF CONSFLAG | ||
| 470 | Key2ndPart DB 0 ; Leftover byte of 2 key codes | ||
| 471 | |||
| 472 | RomData SEGMENT AT 40H | ||
| 473 | ORG 1AH | ||
| 474 | Bufferhead DW ? | ||
| 475 | BufferTail DW ? | ||
| 476 | KeyBuffer LABEL WORD | ||
| 477 | KeyBufLen equ 32 ; length of KeyBuffer | ||
| 478 | RomData 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 | |||
| 484 | Break PROC NEAR | ||
| 485 | mov Key2ndPart,3 ; Force next char to be ^C( stop ) | ||
| 486 | IRET | ||
| 487 | Break ENDP | ||
| 488 | |||
| 489 | SUBTTL Console read and subroutines | ||
| 490 | PAGE | ||
| 491 | |||
| 492 | COMMENT * | ||
| 493 | The console read dispatch tries to read the selected number of | ||
| 494 | characters from the keyboard. If at any point there is no key in | ||
| 495 | the queue, it returns to the dos to allow another process to run | ||
| 496 | until a key is depressed. | ||
| 497 | |||
| 498 | Entry 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 | |||
| 503 | Exit parameters: | ||
| 504 | CX Number of characters left to read | ||
| 505 | DS:BX Pointer to device request packet | ||
| 506 | * | ||
| 507 | |||
| 508 | Con$Read PROC NEAR | ||
| 509 | JCXZ StatusComplete | ||
| 510 | CON$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 | ||
| 517 | Con$Read ENDP | ||
| 518 | |||
| 519 | COMMENT * | ||
| 520 | ChrIn attempts to read a character from the keyboard queue that | ||
| 521 | is maintained by the ROM BIOS. If the queue is not empty, the code | ||
| 522 | is returned. Otherwise, the packet is added to the list of keyboard | ||
| 523 | reads and carry is set to cause the driver routine to return to the | ||
| 524 | dos with the done bit not set which results in an I/O wait. | ||
| 525 | |||
| 526 | Entry parameters: | ||
| 527 | DS:BX Pointer to device request packet | ||
| 528 | |||
| 529 | Exit parameters: | ||
| 530 | AL Character from keyboard if present | ||
| 531 | * | ||
| 532 | |||
| 533 | ChrIn PROC NEAR | ||
| 534 | ConReadLoop: | ||
| 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 | ||
| 546 | ALT15: | ||
| 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 | ||
| 550 | KeyRet: RET | ||
| 551 | ChrIn ENDP | ||
| 552 | |||
| 553 | |||
| 554 | COMMENT * | ||
| 555 | The non-destructive keyboard read routine returns the next char | ||
| 556 | in the queue if there is one. | ||
| 557 | |||
| 558 | Entry parameters: | ||
| 559 | DS:BX Pointer to device request packet | ||
| 560 | |||
| 561 | Exit parameters: | ||
| 562 | DS:BX Pointer to device request packet | ||
| 563 | * | ||
| 564 | Con$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 | ||
| 576 | NOTBRK: CMP AX,7200H ;CHECK FOR CTRL-PRTSC | ||
| 577 | JNZ RDexit | ||
| 578 | MOV AL,16 | ||
| 579 | RDexit: | ||
| 580 | MOV [BX].MEDIA,AL | ||
| 581 | EXVEC: JMP StatusComplete | ||
| 582 | CONBUS: JMP StatusDevReady | ||
| 583 | Con$RdNd ENDP | ||
| 584 | |||
| 585 | ;-------------------------------------------------------------- | ||
| 586 | ; | ||
| 587 | ; KEYBOARD FLUSH ROUTINE | ||
| 588 | ; | ||
| 589 | Con$Flsh PROC NEAR | ||
| 590 | MOV [Key2ndPart],0 ;Clear out holding buffer | ||
| 591 | |||
| 592 | CALL Flush ; Flush the keyboard | ||
| 593 | JMP EXVEC | ||
| 594 | Con$Flsh ENDP | ||
| 595 | |||
| 596 | |||
| 597 | Flush 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 | ||
| 612 | Flush ENDP | ||
| 613 | |||
| 614 | SUBTTL Console output( video ) routines | ||
| 615 | PAGE | ||
| 616 | |||
| 617 | ;---------------------------------------------------------- | ||
| 618 | ; | ||
| 619 | ; CONSOLE WRITE ROUTINE | ||
| 620 | ; | ||
| 621 | CON$WRIT: | ||
| 622 | JCXZ EXVEC | ||
| 623 | CON$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 | |||
| 633 | SUBTTL Keyboard interrupt routine | ||
| 634 | PAGE | ||
| 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 | |||
| 645 | OldKeyInterrupt DD ? | ||
| 646 | KeySem db 0 ; non-zero if someone waiting on input | ||
| 647 | |||
| 648 | KeyboardInterrupt 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 | ||
| 666 | kbi1: | ||
| 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 | ||
| 673 | kbi2: | ||
| 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 | ||
| 690 | NoKey: | ||
| 691 | IRET | ||
| 692 | KeyBoardInterrupt 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 | |||
| 710 | OldKbdHandler dd ? | ||
| 711 | |||
| 712 | ;------------------------------------------------------------- | ||
| 713 | |||
| 714 | KeyBoardHandler proc far | ||
| 715 | or ah,ah | ||
| 716 | je DoLocalRead | ||
| 717 | cmp ah,1 | ||
| 718 | je DoLocalStat | ||
| 719 | OldKBint: | ||
| 720 | jmp [OldKbdHandler] | ||
| 721 | |||
| 722 | DoLocalStat: | ||
| 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 | |||
| 733 | DoLocalRead: | ||
| 734 | push ax | ||
| 735 | push bx | ||
| 736 | push cx | ||
| 737 | push dx | ||
| 738 | DoLocalRd1: | ||
| 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 | |||
| 750 | DoLocalRd2: | ||
| 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 | |||
| 765 | LocalRead: | ||
| 766 | pop dx | ||
| 767 | pop cx | ||
| 768 | pop bx | ||
| 769 | pop ax | ||
| 770 | jmp [OldKbdHandler] ; read the character and return | ||
| 771 | |||
| 772 | KeyBoardHandler endp | ||
| 773 | |||
| 774 | ENDIF ;CONSFLAG | ||
| 775 | |||
| 776 | SUBTTL Aux driver | ||
| 777 | ;------------------------------------------------------ | ||
| 778 | ; | ||
| 779 | ; A U X - AUXILARY DEVICE DRIVER | ||
| 780 | ; | ||
| 781 | AUXDEV 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 | ||
| 789 | COM1DEV LABEL WORD | ||
| 790 | DW LPT1DEV,BIOSEG | ||
| 791 | DW 1000000000000000B | ||
| 792 | DW STRATEGY | ||
| 793 | DW AUX0$IN | ||
| 794 | DB 'COM1 ' | ||
| 795 | |||
| 796 | COM2DEV LABEL WORD | ||
| 797 | DW -1,BIOSEG | ||
| 798 | DW 1000000000000000B | ||
| 799 | DW STRATEGY | ||
| 800 | DW AUX1$IN | ||
| 801 | DB 'COM2 ' | ||
| 802 | |||
| 803 | AUXBUF DB 0,0 | ||
| 804 | ;------------------------------------------------------- | ||
| 805 | ; | ||
| 806 | ; READ FROM AUXILARY DEVICE | ||
| 807 | ; | ||
| 808 | AUX$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 | ||
| 815 | AUX1: CALL AUXIN | ||
| 816 | AUX2: STOSB ;STORE CHARACTER | ||
| 817 | LOOP AUX1 | ||
| 818 | EXVEC2: JMP StatusComplete | ||
| 819 | |||
| 820 | AUXIN: 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 | ||
| 827 | AROK: RET | ||
| 828 | ;-------------------------------------------------------- | ||
| 829 | ; | ||
| 830 | ; AUX NON-DESTRUCTIVE READ, NO WAITING | ||
| 831 | ; | ||
| 832 | AUX$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 | ||
| 845 | AUXRDX: JMP StatusComplete | ||
| 846 | AUXBUS: JMP StatusDevReady | ||
| 847 | ;---------------------------------------------------------- | ||
| 848 | ; | ||
| 849 | ; AUX OUTPUT STATUS | ||
| 850 | ; | ||
| 851 | AUX$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 | |||
| 859 | AUXSTAT: | ||
| 860 | MOV AH,3 | ||
| 861 | AUXOP: CALL GETDX | ||
| 862 | INT 14H | ||
| 863 | RET | ||
| 864 | ;--------------------------------------------------------- | ||
| 865 | ; | ||
| 866 | ; FLUSH AUX INPUT BUFFER | ||
| 867 | ; | ||
| 868 | AUX$FLSH: | ||
| 869 | CALL GETBX | ||
| 870 | MOV BYTE PTR [BX],0 | ||
| 871 | JMP EXVEC2 | ||
| 872 | ;--------------------------------------------------------- | ||
| 873 | ; | ||
| 874 | ; WRITE TO AUXILARY DEVICE | ||
| 875 | ; | ||
| 876 | AUX$WRIT: | ||
| 877 | JCXZ EXVEC2 | ||
| 878 | AUX$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 | ||
| 887 | AWOK: LOOP AUX$LOOP | ||
| 888 | JMP EXVEC2 | ||
| 889 | |||
| 890 | GETBX: CALL GETDX | ||
| 891 | MOV BX,DX | ||
| 892 | ADD BX,OFFSET AUXBUF | ||
| 893 | RET | ||
| 894 | SUBTTL Printer driver | ||
| 895 | ;------------------------------------------------------------- | ||
| 896 | ; | ||
| 897 | ; P R N - PRINTER DEVICE | ||
| 898 | ; | ||
| 899 | PRNDEV LABEL WORD ;HEADER FOR DEVICE "PRN" | ||
| 900 | DW TIMDEV,BIOSEG | ||
| 901 | DW 1000000000000000B | ||
| 902 | DW STRATEGY | ||
| 903 | DW PRN0$IN | ||
| 904 | DB 'PRN ' | ||
| 905 | |||
| 906 | LPT1DEV LABEL WORD | ||
| 907 | DW LPT2DEV,BIOSEG | ||
| 908 | DW 1000000000000000B | ||
| 909 | DW STRATEGY | ||
| 910 | DW PRN0$IN | ||
| 911 | DB 'LPT1 ' | ||
| 912 | |||
| 913 | LPT2DEV LABEL WORD | ||
| 914 | DW LPT3DEV,BIOSEG | ||
| 915 | DW 1000000000000000B | ||
| 916 | DW STRATEGY | ||
| 917 | DW PRN1$IN | ||
| 918 | DB 'LPT2 ' | ||
| 919 | |||
| 920 | LPT3DEV LABEL WORD | ||
| 921 | DW COM2DEV,BIOSEG | ||
| 922 | DW 1000000000000000B | ||
| 923 | DW STRATEGY | ||
| 924 | DW PRN2$IN | ||
| 925 | DB 'LPT3 ' | ||
| 926 | |||
| 927 | ERRFLG DB 0 | ||
| 928 | |||
| 929 | ;---------------------------------------------------------- | ||
| 930 | ; | ||
| 931 | ; WRITE TO PRINTER DEVICE | ||
| 932 | ; | ||
| 933 | PRN$WRIT: | ||
| 934 | JCXZ EXVEC3 | ||
| 935 | PRN$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 | |||
| 940 | PRETRY: XOR AH,AH ;AH=0 | ||
| 941 | CALL PRNOP ;TO INDICATE PRINT CHAR IN AL | ||
| 942 | |||
| 943 | ERRCHK: JZ PROK | ||
| 944 | XOR [ERRFLG],1 ;DO 1 AUTOMATIC RETRY | ||
| 945 | JNZ PRETRY | ||
| 946 | PMESSG: JMP StatusPartialXfer ;RETURN WITH THE ERROR | ||
| 947 | |||
| 948 | PROK: LOOP PRN$LOOP | ||
| 949 | EXVEC3: JMP StatusComplete | ||
| 950 | ;-------------------------------------------------------- | ||
| 951 | ; | ||
| 952 | ; PRINTER STATUS ROUTINE | ||
| 953 | ; | ||
| 954 | PRN$STAT: | ||
| 955 | CALL PRNSTAT ;DEVICE IN DX | ||
| 956 | JNZ PMESSG | ||
| 957 | TEST AH,10000000B | ||
| 958 | JNZ EXVEC3 | ||
| 959 | JMP StatusDevReady | ||
| 960 | |||
| 961 | PRNSTAT: | ||
| 962 | MOV AH,2 | ||
| 963 | PRNOP: 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 | ||
| 977 | PRNOP1: OR AL,AL ;SET NZ FLAG | ||
| 978 | PRNOP2: RET | ||
| 979 | |||
| 980 | SUBTTL 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 | ||
| 994 | TIMDEV LABEL WORD | ||
| 995 | DW Floppydevice,BIOSEG | ||
| 996 | DW 1000000000001000B | ||
| 997 | DW STRATEGY | ||
| 998 | DW TIM$IN | ||
| 999 | DB 'CLOCK$ ' | ||
| 1000 | |||
| 1001 | DAYCNT 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 | |||
| 1017 | TIM$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 | ||
| 1058 | TIM$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 | |||
| 1089 | SUBTTL Clock interrupt and replacement for ROM code | ||
| 1090 | PAGE | ||
| 1091 | |||
| 1092 | COMMENT * | ||
| 1093 | The clock code in the ROM is replaced with the following code which | ||
| 1094 | provides the clock interface to the scheduler and a 1 ms time base. The | ||
| 1095 | 1AH interrupt is simulated to return the approximate time for those | ||
| 1096 | routines which still call 1AH. The time period for motor start up is | ||
| 1097 | preserved since that code has not yet been rewritten. | ||
| 1098 | * | ||
| 1099 | |||
| 1100 | RomData SEGMENT AT 040H | ||
| 1101 | ORG 03FH | ||
| 1102 | Motor_Status DB 1 DUP(?) | ||
| 1103 | Motor_Count DB 1 DUP(?) | ||
| 1104 | RomData ENDS | ||
| 1105 | |||
| 1106 | TickLow DW ? ; Low part of time in Msec | ||
| 1107 | TickHigh DW ? ; High part of time in msec | ||
| 1108 | MotorFlag DB 0 ; There is an active motor | ||
| 1109 | MotorTick DB MOTORCOUNT ; # ticks until 1/18.2 secs | ||
| 1110 | SchedTick DB SCHEDCOUNT ; Scheduler countdown | ||
| 1111 | |||
| 1112 | ; Interrupt 8H - timer interrupt | ||
| 1113 | |||
| 1114 | ASSUME DS:NOTHING | ||
| 1115 | TimerInterrupt PROC FAR | ||
| 1116 | PUSH AX | ||
| 1117 | INC TickLow | ||
| 1118 | JNZ NoOverflow | ||
| 1119 | INC TickHigh | ||
| 1120 | NoOverFlow: | ||
| 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 | ||
| 1130 | NotDay: | ||
| 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. | ||
| 1164 | CheckSched: | ||
| 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 | ||
| 1178 | csch1: 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 | ||
| 1187 | NoSchedActive: | ||
| 1188 | IRET ; All done | ||
| 1189 | |||
| 1190 | NoSched: | ||
| 1191 | POP AX | ||
| 1192 | INTRET: IRET ; All done | ||
| 1193 | TimerInterrupt ENDP | ||
| 1194 | |||
| 1195 | ; INT 1AH - Get/Set time based in 55msec tick | ||
| 1196 | |||
| 1197 | TimeOfDay 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 | ||
| 1205 | ReadOld: | ||
| 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 | ||
| 1218 | WriteOld: | ||
| 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 | ||
| 1231 | TimeOfDay ENDP | ||
| 1232 | |||
| 1233 | ;++++ | ||
| 1234 | memsizmsg db 13,10,'Error - Interrupt 12',13,10,0 | ||
| 1235 | memsizint dd 0 | ||
| 1236 | |||
| 1237 | memsizhandler 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 | ||
| 1251 | memsizhandler endp | ||
| 1252 | ;++++ | ||
| 1253 | |||
| 1254 | ;---------------------------------------------- | ||
| 1255 | ; WRITE OUT MESSAGE POINTED TO BY [SI] | ||
| 1256 | ; | ||
| 1257 | WRMSG: 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 | ||
| 1264 | WRMRET: RET | ||
| 1265 | |||
| 1266 | .xlist | ||
| 1267 | INCLUDE BUGCODE.INC | ||
| 1268 | .list | ||
| 1269 | |||
| 1270 | Code ENDS | ||
| 1271 | |||
| 1272 | SUBTTL Diskette driver -- now used only for bootup | ||
| 1273 | ;----------------------------------------------------------------- | ||
| 1274 | ; | ||
| 1275 | ; DISK INTERFACE ROUTINES | ||
| 1276 | ; | ||
| 1277 | BiosInit SEGMENT PARA PUBLIC 'CODE' | ||
| 1278 | |||
| 1279 | DRVMAX DB 4 | ||
| 1280 | |||
| 1281 | ASSUME CS:BiosSeg | ||
| 1282 | |||
| 1283 | MAXERR = 5 | ||
| 1284 | LSTDRV = 504H | ||
| 1285 | |||
| 1286 | WRTVERIFY LABEL WORD | ||
| 1287 | RFLAG DB 2 ;2 for read, 3 for write | ||
| 1288 | VERIFY DB 0 ;1 if verify after write | ||
| 1289 | SINGLE DB 0 ;1 if single drive system | ||
| 1290 | SWPFLG DB 0 ;1 if BIOS swapped out | ||
| 1291 | SECCNT DW 0 | ||
| 1292 | HARDNUM DB 99 ;logical drive number of first hardfile | ||
| 1293 | |||
| 1294 | RESSEC = 3 | ||
| 1295 | DRVLIM = 8 ;Number of sectors on device | ||
| 1296 | SECLIM = 13 ;MAXIMUM SECTOR | ||
| 1297 | HDLIM = 15 ;MAXIMUM HEAD | ||
| 1298 | HIDSEC = 17 ;NUMBER OF HIDDEN SECTORS | ||
| 1299 | |||
| 1300 | ;WARNING - preserve order of drive and curhd! -c.p. | ||
| 1301 | |||
| 1302 | DRIVE DB 0 ;PHYSICAL DRIVE CODE | ||
| 1303 | CURHD DB 0 ;CURRENT HEAD | ||
| 1304 | CURSEC DB 0 ;CURRENT SECTOR | ||
| 1305 | CURTRK DW 0 ;CURRENT TRACK | ||
| 1306 | |||
| 1307 | |||
| 1308 | ERRIN: ;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 | ||
| 1315 | LSTERR DB 0 ;ALL OTHER ERRORS | ||
| 1316 | |||
| 1317 | |||
| 1318 | ERROUT: ;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 | |||
| 1327 | NUMERR= ERROUT-ERRIN | ||
| 1328 | ;--------------------------------------------------------------------- | ||
| 1329 | SPSAV DW 0 ;SAVE THE STACK POINTER | ||
| 1330 | ; | ||
| 1331 | |||
| 1332 | GETBP: 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 | ||
| 1341 | GOODID: 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 | |||
| 1348 | GETBP1: 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 | ||
| 1358 | HAS8: 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 | ||
| 1364 | HAS1: 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 | ||
| 1371 | GETRET: POP BX | ||
| 1372 | RET88: 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 | ||
| 1380 | FDRIVE: | ||
| 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 | ; | ||
| 1408 | DISKRD: | ||
| 1409 | debug 1,4,<DISKRD: $x $x $x $x:$x\n>,<ax,cx,dx,es,di> | ||
| 1410 | MOV [RFLAG],2 | ||
| 1411 | DISKIO: | ||
| 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 | ||
| 1425 | STCRET: STC | ||
| 1426 | IORET: RET | ||
| 1427 | |||
| 1428 | INRANGE: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 | |||
| 1435 | NOTHARD:CMP [SINGLE],1 ;SINGLE FLOPPY INSTALLED? | ||
| 1436 | JNZ RDWR | ||
| 1437 | CALL SWPDSK ;ASK USER FOR CORRECT DISK | ||
| 1438 | RDWR: | ||
| 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 | ||
| 1472 | FIRBLK: | ||
| 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 | ||
| 1483 | BUFIO: | ||
| 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 | ||
| 1500 | DONE: | ||
| 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 | |||
| 1507 | SWAP: 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 | ||
| 1516 | SWAP1: 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 | ||
| 1527 | RETZ: RET | ||
| 1528 | |||
| 1529 | ;Read the number of sectors specified in AL, handling track boundaries | ||
| 1530 | |||
| 1531 | BLOCK: 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 | ||
| 1540 | DOIO: | ||
| 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 | |||
| 1556 | DISK1: MOV AL,1 ;Only one sector for buffered I/O | ||
| 1557 | |||
| 1558 | DISK: MOV SI,MAXERR | ||
| 1559 | MOV AH,RFLAG ;Get read/write indicator | ||
| 1560 | |||
| 1561 | RETRY: PUSH AX | ||
| 1562 | |||
| 1563 | CALLROM: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 | ||
| 1581 | NOVERIFY: | ||
| 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 | ||
| 1599 | NOXOR: MOV [CURHD],DH | ||
| 1600 | |||
| 1601 | RET1: RET | ||
| 1602 | |||
| 1603 | DSKERR: | ||
| 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 ;*** | ||
| 1613 | DSKERR1:POP AX ;Restore sector count | ||
| 1614 | JMP RETRY | ||
| 1615 | |||
| 1616 | HARDERR: | ||
| 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 | ||
| 1623 | HARD1: 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 | |||
| 1636 | INITAB DW FDRIVE | ||
| 1637 | DW FDRIVE | ||
| 1638 | DW FDRIVE | ||
| 1639 | DW FDRIVE | ||
| 1640 | INITABH DW HDRIVE | ||
| 1641 | DW DRIVEX | ||
| 1642 | |||
| 1643 | RomData SEGMENT AT 040H | ||
| 1644 | ORG 03EH | ||
| 1645 | Seek_Status DB 1 DUP(?) | ||
| 1646 | RomData ENDS | ||
| 1647 | |||
| 1648 | |||
| 1649 | ;------------------------------------------------- | ||
| 1650 | ; | ||
| 1651 | ; ASK TO SWAP THE DISK IN DRIVE A: | ||
| 1652 | ; | ||
| 1653 | SWPDSK: 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 | ||
| 1671 | RDWR0: | ||
| 1672 | POP DS | ||
| 1673 | XOR AL,AL ;Always use drive 0 | ||
| 1674 | RET | ||
| 1675 | |||
| 1676 | |||
| 1677 | SNGMSG DB CR,LF,"Insert diskette for drive " | ||
| 1678 | DRVLET DB "A: and strike",CR,LF,"any key when ready",CR,LF,LF,0 | ||
| 1679 | HNUM DB 0 ;NUMBER OF HARDFILES | ||
| 1680 | |||
| 1681 | |||
| 1682 | ;** End of Permanently Resident BIOS | ||
| 1683 | |||
| 1684 | |||
| 1685 | HARDDRV DB 80H ;Physical drive number of first hardfile | ||
| 1686 | ;********************************************************************** | ||
| 1687 | ; "HDRIVE" IS A HARD DISK WITH 512 BYTE SECTORS | ||
| 1688 | ;********************************************************************* | ||
| 1689 | HDRIVE: | ||
| 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 | ;********************************************************************* | ||
| 1705 | DRIVEX: | ||
| 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 | |||
| 1718 | SUBTTL 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 | |||
| 1740 | DRVFAT DW 0000 ;DRIVE AND FAT ID OF DOS | ||
| 1741 | BIOS$ DW 0000 ;FIRST SECTOR OF DATA | ||
| 1742 | DOSCNT DW 0000 ;HOW MANY SECTORS TO READ | ||
| 1743 | |||
| 1744 | BootBufr EQU 17C0H ; High memory scratch area | ||
| 1745 | |||
| 1746 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 1747 | |||
| 1748 | INIT: 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 | |||
| 1777 | IF 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 | ||
| 1782 | ENDIF | ||
| 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 | ||
| 1810 | IF 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 | ||
| 1820 | ELSE | ||
| 1821 | ADD DI,4 | ||
| 1822 | ENDIF | ||
| 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 | ||
| 1848 | IF 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 | ||
| 1860 | ELSE | ||
| 1861 | ADD DI,4*4 ; skip 16 - 19 | ||
| 1862 | ENDIF ;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 | ||
| 1938 | NOTSNGL: | ||
| 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 | ||
| 1947 | ENDDRV: | ||
| 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 | |||
| 1961 | NOTOK: MOV [HARDDRV],DL | ||
| 1962 | MOV DI,OFFSET CS:HDRIVE | ||
| 1963 | DEC [HNUM] | ||
| 1964 | CMP [HNUM],0 | ||
| 1965 | JZ ITSOK1 | ||
| 1966 | SETIT: CALL SETHRD ;SET UP SECOND HARDFILE | ||
| 1967 | JNC ITSOK | ||
| 1968 | DEC [HNUM] | ||
| 1969 | |||
| 1970 | ; End of drive initialization | ||
| 1971 | |||
| 1972 | ITSOK: 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 | |||
| 1980 | ITSOK1: CMP BYTE PTR [SINGLE],1 | ||
| 1981 | JMP SHORT GOINIT | ||
| 1982 | |||
| 1983 | ASSUME DS:BiosSeg | ||
| 1984 | |||
| 1985 | ITSOK2: | ||
| 1986 | DEC AL | ||
| 1987 | |||
| 1988 | GOINIT: | ||
| 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 | ||
| 2014 | LOADIT: 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 | |||
| 2026 | SUBTTL Routines for reading in MSDOS | ||
| 2027 | |||
| 2028 | ; | ||
| 2029 | ; READ A FAT SECTOR INTO 17C0:0 | ||
| 2030 | ; | ||
| 2031 | GETFAT: 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 | ; | ||
| 2043 | GETBOOT: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 | ; | ||
| 2060 | SETHRD: 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 | ||
| 2072 | SET1: CMP BYTE PTR ES:[BX],1 | ||
| 2073 | JZ SET2 | ||
| 2074 | ADD BX,16 | ||
| 2075 | CMP BX,202H | ||
| 2076 | JNZ SET1 | ||
| 2077 | SETRET: STC ;NOT FOUND SO USE DEFAULTS | ||
| 2078 | RET | ||
| 2079 | |||
| 2080 | SET2: 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 | ||
| 2112 | SET3: | ||
| 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 | ; | ||
| 2141 | GETCLUS: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 | |||
| 2152 | GETCL1: 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 | |||
| 2159 | GETCL2: 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 | ; | ||
| 2174 | UNPACK: 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 | ||
| 2186 | HAVCLUS:AND BX,0FFFH | ||
| 2187 | POP SI | ||
| 2188 | POP DS | ||
| 2189 | RET | ||
| 2190 | ; | ||
| 2191 | ; SI POINTS TO DEVICE HEADER | ||
| 2192 | ; | ||
| 2193 | PRINT_INIT: | ||
| 2194 | MOV BH,1 | ||
| 2195 | MOV DL,17H | ||
| 2196 | JMP SHORT DEV_INIT | ||
| 2197 | AUX_INIT: | ||
| 2198 | MOV BX,RSINIT | ||
| 2199 | MOV DL,14H | ||
| 2200 | DEV_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 | ||
| 2208 | INTNUM DB 17H | ||
| 2209 | RET | ||
| 2210 | |||
| 2211 | END$: | ||
| 2212 | |||
| 2213 | BiosInit 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 @@ | |||
| 1 | TITLE DISK - MS-DOS 4.0 disk drivers for IBM | ||
| 2 | NAME DISK | ||
| 3 | |||
| 4 | PAGE ,132 | ||
| 5 | |||
| 6 | ;DEBUGFLG=1 | ||
| 7 | |||
| 8 | .xlist | ||
| 9 | INCLUDE DEFDBUG.INC | ||
| 10 | .list | ||
| 11 | |||
| 12 | ; Constants | ||
| 13 | |||
| 14 | ErrLim= 5 ; Number of retries on error | ||
| 15 | |||
| 16 | ; Floppy delay constants | ||
| 17 | |||
| 18 | DelayLoad= 35 ; 35 milliseconds to load head | ||
| 19 | |||
| 20 | ; Constants for floppy disk controller | ||
| 21 | |||
| 22 | Rate99= 000H ; Step rate 96tpi disk in 96tpi drive | ||
| 23 | Rate49= 001H ; Step rate 48tpi disk in 96tpi drive | ||
| 24 | Rate44= 002H ; Step rate 48tpi disk in 48tpi drive | ||
| 25 | |||
| 26 | ; Commands to floppy disk controller | ||
| 27 | |||
| 28 | FD_CRESET= 007H ; Recalibrate drive | ||
| 29 | FD_CSENSE= 008H ; Sense interrupt status | ||
| 30 | FD_CSEEK= 00FH ; Seek to another track | ||
| 31 | FD_CREAD= 046H ; MFM read, skip deleted data | ||
| 32 | FD_CWRITE= 045H ; MFM write, skip deleted data | ||
| 33 | FD_CSPEC= 003H ; Special - step rate, head load/unload | ||
| 34 | |||
| 35 | ; Status codes | ||
| 36 | |||
| 37 | FD_SDIO= 01000000B ; Transfer direction (0 -> controller) | ||
| 38 | FD_SRQM= 10000000B ; Controller ready for next data | ||
| 39 | |||
| 40 | ; Hard disk controller commands | ||
| 41 | HD_CSENS= 03H ; request sense block | ||
| 42 | HD_CREAD= 08H ; read | ||
| 43 | HD_CWRITE= 0AH ; write | ||
| 44 | |||
| 45 | HDcontrolbyte= 05H ; step rate = 70 us. | ||
| 46 | |||
| 47 | ; I/O ports | ||
| 48 | |||
| 49 | FD_PSEL= 03F2H ; Controls drive select and motors | ||
| 50 | FD_PDAT= 03F5H ; Data transfer to/from controller | ||
| 51 | FD_PSTAT= 03F4H ; Controller status | ||
| 52 | FD_PCMD= 03F7H ; Controller command register | ||
| 53 | |||
| 54 | HD_PDAT= 0320H ; read/write data | ||
| 55 | HD_PSTAT= 0321H ; controller status | ||
| 56 | HD_PSEL= 0322H ; controller select | ||
| 57 | HD_PMSK= 0323H ; DMA and interrupt mask bits | ||
| 58 | |||
| 59 | PDMA= 0 ; Base of ports for DMA control | ||
| 60 | PDMAX= 7FH ; Address extension regs for DMA | ||
| 61 | ;NOTE base address suitable for ch. 2 & 3 only | ||
| 62 | FD_DMA= 2 ; floppy disk DMA channel | ||
| 63 | HD_DMA= 3 ; hard disk DMA channel | ||
| 64 | |||
| 65 | DMA_READ= 44H ; DMA read command | ||
| 66 | DMA_WRITE= 48H ; DMA write command | ||
| 67 | |||
| 68 | ; Misc | ||
| 69 | |||
| 70 | DORmask= 00CH ; Not reset, enable DMA & interrupt | ||
| 71 | |||
| 72 | |||
| 73 | |||
| 74 | SUBTTL Data for performing requests | ||
| 75 | PAGE + | ||
| 76 | |||
| 77 | ;* Dos Request Packet structure | ||
| 78 | |||
| 79 | DosPacket 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 | ||
| 91 | DosPacket 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 | ||
| 98 | Start= 0 ; Starting I/O | ||
| 99 | Calc= 1 ; Calculate position on disk | ||
| 100 | Done= 7 ; I/O is done | ||
| 101 | Idle= 8 ; Drive is inactive | ||
| 102 | Error= 9 ; Have an error | ||
| 103 | ; The following states are used by the floppy driver only | ||
| 104 | Select= 2 ; Select drive, start motor, seek | ||
| 105 | Recal= 3 ; Drive was just recalibrated | ||
| 106 | Seek= 4 ; Seek just finished | ||
| 107 | Settle= 5 ; Head has settled | ||
| 108 | RdWri= 6 ; Read/write is done | ||
| 109 | ; The following states are used by the fixed driver only | ||
| 110 | Verify= 6 ; Start verify portion of write | ||
| 111 | |||
| 112 | |||
| 113 | DeviceStruc 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 | ||
| 138 | DeviceStruc 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 | |||
| 150 | BiosSeg GROUP Code,BiosInit | ||
| 151 | |||
| 152 | Code SEGMENT BYTE PUBLIC 'CODE' | ||
| 153 | ASSUME CS:BiosSeg | ||
| 154 | |||
| 155 | IFDEF DEBUGFLG | ||
| 156 | EXTRN BUGBITS:BYTE,DPRINTF:NEAR | ||
| 157 | ENDIF | ||
| 158 | |||
| 159 | SUBTTL Device data | ||
| 160 | PAGE + | ||
| 161 | |||
| 162 | Floppy DeviceStruc <> | ||
| 163 | Fixed DeviceStruc <> | ||
| 164 | |||
| 165 | ;* Per drive information, including BPBs | ||
| 166 | |||
| 167 | DriveStruc 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 | ||
| 183 | DriveStruc ENDS | ||
| 184 | |||
| 185 | ; DrvFlag values | ||
| 186 | Frestor= 1 ; restore needed | ||
| 187 | Fmotoron= 2 ; motor is on | ||
| 188 | |||
| 189 | DriveA DriveStruc <> ; floppy drive 0 | ||
| 190 | DriveB DriveStruc <> ; floppy drive 1 or 0 | ||
| 191 | DriveC DriveStruc <> ; hard drive 0 or floppy drive 2 | ||
| 192 | DriveD DriveStruc <> ; hard drive 1 or floppy drive 3 | ||
| 193 | |||
| 194 | FDinfo DW DriveA | ||
| 195 | DW DriveB | ||
| 196 | HDinfo DW DriveC | ||
| 197 | DW DriveD | ||
| 198 | |||
| 199 | |||
| 200 | ; Structure of parameter block for floppy pointed to by 0:4*1E | ||
| 201 | |||
| 202 | FloppyParameter 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 | ||
| 216 | FloppyParameter ENDS | ||
| 217 | |||
| 218 | |||
| 219 | ScratchBuffer DB 512 DUP(?) ; Scratch buffer for when DMA fails | ||
| 220 | ; Hope we don't handle >512 sector | ||
| 221 | ; size | ||
| 222 | |||
| 223 | ;* Miscellaneous data | ||
| 224 | |||
| 225 | Single DB 0 ; non-zero if 1 floppy disk system | ||
| 226 | ; in this case, NumFloppy will be 2 | ||
| 227 | |||
| 228 | SUBTTL Data for interface to 4.0 | ||
| 229 | PAGE + | ||
| 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 | |||
| 240 | int_savregs= 32H ; interrupt routine which saves all regs | ||
| 241 | |||
| 242 | |||
| 243 | SwapSem1 DB 0 ; non-zero if waiting to swap disks | ||
| 244 | SwapSem2 DB 0 ; non-zero if waiting to prompt for swap | ||
| 245 | ScratchBufSem DB 0 ; semaphore controlling ScratchBuffer | ||
| 246 | |||
| 247 | SEM_WANT= 2 | ||
| 248 | SEM_BUSY= 1 | ||
| 249 | |||
| 250 | SemWait Macro wchan | ||
| 251 | local l1,l2 | ||
| 252 | pushf | ||
| 253 | l1: 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 | ||
| 263 | l2: or wchan,SEM_BUSY ;;claim semaphore | ||
| 264 | popf | ||
| 265 | endm | ||
| 266 | |||
| 267 | SemSig Macro wchan | ||
| 268 | local 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] | ||
| 275 | l: and wchan,NOT (SEM_WANT+SEM_BUSY) | ||
| 276 | endm | ||
| 277 | |||
| 278 | |||
| 279 | FloppyQueue DD 0 ; List of requests for floppy | ||
| 280 | FixedQueue DD 0 ; List of requests for fixed disk | ||
| 281 | |||
| 282 | ; Device driver headers | ||
| 283 | |||
| 284 | PUBLIC FloppyDevice | ||
| 285 | FloppyDevice 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 | ||
| 290 | NumFloppy DB 4 ; Handle 4 floppys maximum | ||
| 291 | DB 0 ; can be addressed as word also | ||
| 292 | |||
| 293 | EXTRN Com1Dev:NEAR | ||
| 294 | |||
| 295 | FixedDevice 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) | ||
| 300 | NumFixed 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 | |||
| 312 | JustReturn PROC FAR | ||
| 313 | RET | ||
| 314 | JustReturn ENDP | ||
| 315 | |||
| 316 | FloppyRequest 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 | ||
| 321 | FloppyRequest ENDP | ||
| 322 | |||
| 323 | ; Dispatch table for actions of the floppy requested by 4.0 | ||
| 324 | |||
| 325 | FloppyFunction 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 | |||
| 344 | FixedRequest 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 | ||
| 349 | FixedRequest ENDP | ||
| 350 | |||
| 351 | ; Dispatch table for actions of the hard disk requested by 4.0 | ||
| 352 | |||
| 353 | FixedFunction 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 | |||
| 373 | SUBTTL Data for routines that make direct Int 13 requests | ||
| 374 | PAGE + | ||
| 375 | |||
| 376 | |||
| 377 | RealInt13Vec dw 0 ; Used to make Int 13 requests | ||
| 378 | dw 0 | ||
| 379 | OldIntDVec dw 0 ; Must be reset when Int 13's on hard | ||
| 380 | dw 0 ; disk. | ||
| 381 | OldIntEVec dw 0 ; Must be reset when Int 13's on floppy | ||
| 382 | dw 0 ; disk. | ||
| 383 | SemDiskIO db 0 ; Semaphore controlling disk io | ||
| 384 | SemInt13 db 0 ; Semaphore controlling Int 13's | ||
| 385 | |||
| 386 | |||
| 387 | SUBTTL 4.0 device driver routines (system entry points) | ||
| 388 | PAGE + | ||
| 389 | |||
| 390 | BiosInit SEGMENT PARA PUBLIC 'CODE' | ||
| 391 | ASSUME CS:BiosSeg | ||
| 392 | |||
| 393 | PUBLIC Disk_Init | ||
| 394 | Disk_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 | ||
| 424 | NOTSNGL: | ||
| 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. | ||
| 437 | ENDDRV: | ||
| 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 | ||
| 453 | NOTOK: | ||
| 454 | MOV DI,OFFSET DriveC | ||
| 455 | DEC [NumFixed] | ||
| 456 | CMP [NumFixed],0 | ||
| 457 | JZ ITSOK | ||
| 458 | SETIT: CALL SETHRD ;SET UP SECOND HARDFILE | ||
| 459 | JNC ITSOK | ||
| 460 | DEC [NumFixed] | ||
| 461 | ITSOK: | ||
| 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 | ||
| 466 | itsok2: | ||
| 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 | ||
| 487 | Disk_Init ENDP | ||
| 488 | |||
| 489 | ; | ||
| 490 | ; READ A BOOT RECORD INTO Scratch buffer | ||
| 491 | ; | ||
| 492 | GETBOOT: | ||
| 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 | ; | ||
| 509 | SETHRD: 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 | ||
| 522 | SET1: CMP BYTE PTR ES:[BX],1 | ||
| 523 | JZ SET2 | ||
| 524 | ADD BX,16 | ||
| 525 | loop SET1 | ||
| 526 | SETRET: STC ;NOT FOUND SO USE DEFAULTS | ||
| 527 | debug 8,3,<Sethrd err rtn: drive $x stat $x\n>,<dx,ax> | ||
| 528 | RET | ||
| 529 | |||
| 530 | SET2: 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 | ||
| 562 | SET3: | ||
| 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 | ||
| 587 | BiosInit ENDS | ||
| 588 | |||
| 589 | ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING | ||
| 590 | |||
| 591 | FloppyInit 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 | ||
| 603 | DBBEG 4,3 | ||
| 604 | jmp SHORT iniret | ||
| 605 | DBEND | ||
| 606 | jmp bpbret | ||
| 607 | ELSE | ||
| 608 | jmp SHORT bpbret | ||
| 609 | ENDIF | ||
| 610 | FloppyInit ENDP | ||
| 611 | |||
| 612 | FixedInit 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 | ||
| 629 | DBBEG 8,3 | ||
| 630 | iniret: debug 12,3,< - Num=$x BPB table=$x:$x\n>,<ax,cs,di> | ||
| 631 | DBEND | ||
| 632 | ENDIF | ||
| 633 | jmp SHORT bpbret | ||
| 634 | FixedInit ENDP | ||
| 635 | |||
| 636 | FloppyBuild PROC | ||
| 637 | mov ah,byte ptr es:[di] | ||
| 638 | call FDGetBPB | ||
| 639 | bpbret: mov [bx.RqMedia],ah | ||
| 640 | mov [bx.RqCount],di | ||
| 641 | mov [bx.RqCount+2],CS | ||
| 642 | jmp StatusComplete | ||
| 643 | FloppyBuild ENDP | ||
| 644 | |||
| 645 | FixedBuild PROC | ||
| 646 | mov ah,byte ptr es:[di] | ||
| 647 | call HDGetBPB | ||
| 648 | jmp SHORT bpbret | ||
| 649 | FixedBuild 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 | |||
| 661 | FloppyCheck 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 | ||
| 671 | flchk1: 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 | ||
| 679 | FloppyCheckDone: | ||
| 680 | MOV BYTE PTR DS:[BX].RqAddr,DL | ||
| 681 | JMP StatusComplete ; Return whether media changed | ||
| 682 | FloppyCheck ENDP | ||
| 683 | |||
| 684 | |||
| 685 | FixedCheck PROC | ||
| 686 | MOV DL,1 | ||
| 687 | JMP FloppyCheckDone | ||
| 688 | FixedCheck 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 | |||
| 709 | FloppyRead LABEL NEAR | ||
| 710 | FloppyWrite LABEL NEAR | ||
| 711 | FloppyWriteV 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 | |||
| 725 | flrw1: OR CX,CX ; Anything to do? | ||
| 726 | JNZ flrw2 ; Yes | ||
| 727 | JMP StatusComplete ; No, all done now | ||
| 728 | flrw2: | ||
| 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 | ||
| 732 | flrw3: | ||
| 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 | ||
| 754 | flrw4: test DS:[BX].RqStatus,0100H ; IO completed? | ||
| 755 | JNZ FloppyIOdone ; yes | ||
| 756 | |||
| 757 | FloppyActive: | ||
| 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 | ||
| 765 | FloppyIOdone: | ||
| 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 | ||
| 771 | FloppyWriteV ENDP | ||
| 772 | |||
| 773 | |||
| 774 | FixedRead LABEL NEAR | ||
| 775 | FixedWrite LABEL NEAR | ||
| 776 | FixedWriteV 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 | |||
| 790 | fxrw1: OR CX,CX ; Anything to do? | ||
| 791 | JNZ fxrw2 ; Yes | ||
| 792 | JMP StatusComplete ; No, all done now | ||
| 793 | fxrw2: | ||
| 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 | ||
| 815 | fxrw4: test DS:[BX].RqStatus,0100H ; IO completed? | ||
| 816 | JNZ FixedIOdone ; yes | ||
| 817 | |||
| 818 | FixedActive: | ||
| 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 | ||
| 826 | FixedIOdone: | ||
| 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 | ||
| 832 | FixedWriteV 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 | |||
| 849 | CheckWrap 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 | |||
| 866 | chkw8: pop cx | ||
| 867 | pop dx | ||
| 868 | ret | ||
| 869 | CheckWrap 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 | |||
| 892 | FloppyChange PROC | ||
| 893 | push cx | ||
| 894 | pushf | ||
| 895 | push bx | ||
| 896 | SemWait SwapSem1 ; Currently waiting to switch disk? | ||
| 897 | pop bx | ||
| 898 | |||
| 899 | flcha1: 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 | ||
| 911 | flcha2: | ||
| 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 | ||
| 922 | flcha4: | ||
| 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 | |||
| 929 | flcha5: | ||
| 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 | ||
| 938 | flcha7: | ||
| 939 | push bx | ||
| 940 | SemSig SwapSem1 ; Allow blocked processes to continue | ||
| 941 | pop bx | ||
| 942 | flcha8: | ||
| 943 | popf | ||
| 944 | pop cx | ||
| 945 | RET | ||
| 946 | |||
| 947 | FloppyChange ENDP | ||
| 948 | |||
| 949 | |||
| 950 | SwitchMsg LABEL WORD | ||
| 951 | DB 13,10,"Insert diskette for drive " | ||
| 952 | DriveLetter LABEL BYTE | ||
| 953 | DB "A: and strike",13,10,"any key when ready",13,10,10,0 | ||
| 954 | |||
| 955 | |||
| 956 | Int13Handler Proc Far | ||
| 957 | push dx ; Save regs used in local processing | ||
| 958 | push cx | ||
| 959 | push bx | ||
| 960 | push ax | ||
| 961 | pushf | ||
| 962 | LockCheck: | ||
| 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 | ||
| 972 | NotLocked: | ||
| 973 | mov SemInt13,1 ; Lock out other disk requests | ||
| 974 | popf | ||
| 975 | pushf | ||
| 976 | BusyCheck: | ||
| 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 | ||
| 986 | DiskFree: | ||
| 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 | ||
| 1011 | Int13Handler endp | ||
| 1012 | |||
| 1013 | |||
| 1014 | SUBTTL Fixed disk startup routine | ||
| 1015 | PAGE + | ||
| 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 | |||
| 1023 | FixedDispatch 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 | |||
| 1035 | FixedExecute 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 | |||
| 1054 | FxExStart: | ||
| 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 | |||
| 1073 | FxExCalc: | ||
| 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 | ||
| 1084 | fxxc1: mov al,DMA_write | ||
| 1085 | mov Fixed.DCB,HD_CWRITE | ||
| 1086 | fxxc2: 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 | ||
| 1109 | fxxc3: 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 | |||
| 1118 | FxExVerify: | ||
| 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 | |||
| 1131 | FxExDone: | ||
| 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 | ||
| 1145 | fxxd1: | ||
| 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 | ||
| 1153 | fxexj4: JMP FixedExecute | ||
| 1154 | |||
| 1155 | fxxd3: | ||
| 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 | |||
| 1166 | FxExIdle: | ||
| 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 | |||
| 1177 | FxExError: | ||
| 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 | ||
| 1192 | fxxe1: | ||
| 1193 | mov ah,12 | ||
| 1194 | fxxe2: 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 | ||
| 1206 | FixedExecute ENDP | ||
| 1207 | |||
| 1208 | ;* Traslation of controller error codes to DOS error codes | ||
| 1209 | |||
| 1210 | HDErrType DW HDErrTyp0 | ||
| 1211 | DW HDErrTyp1 | ||
| 1212 | DW HDErrTyp2 | ||
| 1213 | DW HDErrTyp3 | ||
| 1214 | |||
| 1215 | HDErrTyp0 DB 9, 12, 2, 6,10, 2,12, 6,12, 6 | ||
| 1216 | HDErrTyp1 DB 10, 4, 4, 8,12, 8, 6,12,12, 4, 6 | ||
| 1217 | HDErrTyp2 DB 2, 3, 8 | ||
| 1218 | HDErrTyp3 DB 3, 4, 4, 4 | ||
| 1219 | |||
| 1220 | ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING | ||
| 1221 | |||
| 1222 | FixedInterrupt 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 | ||
| 1243 | fxinot13: | ||
| 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 | ||
| 1265 | fxin0: 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 | ||
| 1272 | fxin1: 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 | ||
| 1280 | fxin4: CALL FixedExecute | ||
| 1281 | fxinret: push ax | ||
| 1282 | MOV AL,20H ; send EOI to 8259 | ||
| 1283 | OUT 20H,AL | ||
| 1284 | pop ax | ||
| 1285 | IRET | ||
| 1286 | FixedInterrupt ENDP | ||
| 1287 | |||
| 1288 | SUBTTL Floppy disk startup routine | ||
| 1289 | PAGE + | ||
| 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 | |||
| 1298 | FloppyDispatch 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 | |||
| 1310 | FloppyExecute 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 | |||
| 1329 | FlExStart: | ||
| 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 | ||
| 1340 | flexj1: 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 | |||
| 1352 | FlExCalc: | ||
| 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 | |||
| 1372 | FlExSelect: | ||
| 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 | |||
| 1382 | NoRestore: ; 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 | |||
| 1397 | FlExRecal: | ||
| 1398 | CALL Sense765 | ||
| 1399 | OR AX,AX ; Error in recal? | ||
| 1400 | JNZ SeekErr ; Yes | ||
| 1401 | RecalOK: | ||
| 1402 | CALL Spec765 ; Load drive specs | ||
| 1403 | MOV Floppy.State,Select ; Back to select state now | ||
| 1404 | flexj2: 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 | |||
| 1413 | FlExSeek: | ||
| 1414 | CALL Sense765 ; Get status of seek | ||
| 1415 | OR AX,AX ; Any error? | ||
| 1416 | JZ SeekOK ; No | ||
| 1417 | SeekErr: | ||
| 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 | |||
| 1424 | SeekOK: | ||
| 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 | |||
| 1439 | FlExSettle: | ||
| 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 | |||
| 1452 | FlExRdWri: | ||
| 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 | |||
| 1459 | RdWriOK: | ||
| 1460 | MOV Floppy.State,Done ; I/O is done | ||
| 1461 | flexj3: 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 | |||
| 1472 | FlExDone: | ||
| 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 | ||
| 1486 | DoneNotWrap: | ||
| 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 | |||
| 1494 | DoneNotWritePart: | ||
| 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 | ||
| 1498 | DoneNotVerify: | ||
| 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 | ||
| 1506 | flexj4: JMP flexj3 | ||
| 1507 | |||
| 1508 | flxd3: | ||
| 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 | |||
| 1519 | FlExIdle: | ||
| 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 | |||
| 1533 | FlExError: | ||
| 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 | |||
| 1541 | FloppyFails: | ||
| 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 | ||
| 1563 | ErrorFound: | ||
| 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 | |||
| 1573 | FloppyExecute ENDP | ||
| 1574 | |||
| 1575 | |||
| 1576 | ASSUME CS:BiosSeg,DS:NOTHING,ES:NOTHING | ||
| 1577 | |||
| 1578 | FloppyInterrupt 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 | ||
| 1588 | flinot13: | ||
| 1589 | TEST Floppy.Flags,Factive ; device active? | ||
| 1590 | JZ flinret ; no, go away | ||
| 1591 | INT int_savregs ; save registers | ||
| 1592 | CALL FloppyExecute | ||
| 1593 | flinret: push ax | ||
| 1594 | MOV AL,20H ; send EOI to 8259 | ||
| 1595 | OUT 20H,AL | ||
| 1596 | pop ax | ||
| 1597 | IRET | ||
| 1598 | FloppyInterrupt ENDP | ||
| 1599 | |||
| 1600 | SUBTTL Timing routines for floppy disk | ||
| 1601 | PAGE + | ||
| 1602 | |||
| 1603 | ;* Data for timers | ||
| 1604 | TimerActive DB 0 ; bit flags for active timers | ||
| 1605 | TimerConv DB 50 ; conversion factor for ms => ticks | ||
| 1606 | Timer1 DB 0 ; One-shot time till restart intr. rtn. | ||
| 1607 | Timer2 DB 0 ; Repetitive 1 Hz timer | ||
| 1608 | Timer2count = 20 ; Reload value for timer2 | ||
| 1609 | |||
| 1610 | MOFFDELAY= 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 | |||
| 1624 | SetTimer1 PROC | ||
| 1625 | TEST AX,AX ; zero count? | ||
| 1626 | JNZ sett10 ; no | ||
| 1627 | CLC | ||
| 1628 | RET | ||
| 1629 | |||
| 1630 | sett10: DIV TimerConv | ||
| 1631 | TEST AH,AH ; remainder? | ||
| 1632 | JZ sett11 | ||
| 1633 | INC AL ; yes, round up | ||
| 1634 | sett11: MOV Timer1,AL | ||
| 1635 | OR TimerActive,1 | ||
| 1636 | debug 4,8,<SetTimer1 $b\n>,<ax> | ||
| 1637 | STC | ||
| 1638 | RET | ||
| 1639 | SetTimer1 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 | |||
| 1651 | SetTimer2 PROC | ||
| 1652 | TEST TimerActive,2 | ||
| 1653 | JNZ sett21 | ||
| 1654 | MOV Timer2,Timer2Count | ||
| 1655 | OR TimerActive,2 | ||
| 1656 | sett21: MOV CS:[BX].Timer,MOFFDELAY | ||
| 1657 | debug 4,8,<SetTimer2\n>,<> | ||
| 1658 | RET | ||
| 1659 | SetTimer2 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 | ||
| 1675 | FloppyTimer PROC FAR | ||
| 1676 | TEST TimerActive,0ffH ; any timers active? | ||
| 1677 | JNZ fltim1 ; yes | ||
| 1678 | RET ; no, return quickly | ||
| 1679 | fltim1: 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 | |||
| 1689 | fltim3: TEST TimerActive,2 ; Timer2 active? | ||
| 1690 | JZ fltim4 ; no | ||
| 1691 | DEC Timer2 ; 1 Hz clock time? | ||
| 1692 | JZ fltim5 ; no | ||
| 1693 | fltim4: JMP fltim9 | ||
| 1694 | fltim5: | ||
| 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 | ||
| 1702 | TimeOutLoop: | ||
| 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 | ||
| 1721 | fltim6: | ||
| 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 | |||
| 1741 | fltim7: INC CH ; Flag still active | ||
| 1742 | fltim8: 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 | ||
| 1748 | fltim9: RET | ||
| 1749 | |||
| 1750 | FloppyTimer ENDP | ||
| 1751 | |||
| 1752 | |||
| 1753 | IFDEF DEBUGFLG | ||
| 1754 | DumpRegs 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 | ||
| 1784 | dmpr0: jmp dmpr0 | ||
| 1785 | DumpRegs ENDP | ||
| 1786 | ENDIF ;DEUBGFLAG | ||
| 1787 | |||
| 1788 | SUBTTL Routines shared between Floppy and Hard disk drivers | ||
| 1789 | PAGE + | ||
| 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 | |||
| 1816 | Setup 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 | ||
| 1835 | SetupDone: | ||
| 1836 | RET | ||
| 1837 | Setup 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 | |||
| 1869 | MapSector 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 | ||
| 1902 | maps2: | ||
| 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 | ||
| 1914 | maps4: | ||
| 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 | ||
| 1943 | REP MOVSB ; Copy the write buffer | ||
| 1944 | POP SI | ||
| 1945 | POP DS | ||
| 1946 | POP ES | ||
| 1947 | maps6: | ||
| 1948 | RET | ||
| 1949 | MapSector 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 | |||
| 1962 | DMAsetup 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 | ||
| 2000 | DMAsetup 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 | |||
| 2016 | DoneRequest 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 | ||
| 2034 | dnrq2: | ||
| 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 | ||
| 2039 | dnrq4: ; 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 | ||
| 2050 | dnrq5: | ||
| 2051 | pop bx | ||
| 2052 | ret | ||
| 2053 | DoneRequest 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 | |||
| 2068 | FDGetBPB 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 | ||
| 2079 | BPBgood: | ||
| 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 | ||
| 2095 | BPBKnowSectors: | ||
| 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 | ||
| 2102 | BPBKnowHeads: | ||
| 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 | ||
| 2110 | BPBdone: | ||
| 2111 | POP DX | ||
| 2112 | POP CX | ||
| 2113 | POP BX | ||
| 2114 | POP AX | ||
| 2115 | RET | ||
| 2116 | FDGetBPB 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 | |||
| 2130 | HDGetBPB 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 | ||
| 2138 | HDGetBPB ENDP | ||
| 2139 | |||
| 2140 | |||
| 2141 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 2142 | |||
| 2143 | BlockIfLocked Proc Near ; Block the current process if it has | ||
| 2144 | pushf ; been locked out by an Int 13 request. | ||
| 2145 | bifl1: 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 | ||
| 2162 | bifl2: | ||
| 2163 | mov SemDiskIO,1 | ||
| 2164 | popf | ||
| 2165 | ret | ||
| 2166 | BlockIfLocked endp | ||
| 2167 | |||
| 2168 | SUBTTL Routines that interface to hard disk controller | ||
| 2169 | PAGE + | ||
| 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 | |||
| 2180 | HDCommand 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 | ||
| 2188 | hdcom1: 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 | ||
| 2196 | hdcom2: 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 | ||
| 2204 | HDCommand 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 | |||
| 2215 | HDWaitReq PROC | ||
| 2216 | mov dx,HD_PSTAT | ||
| 2217 | in al,dx | ||
| 2218 | test al,01h ; request bit? | ||
| 2219 | jz HDWaitReq | ||
| 2220 | ret | ||
| 2221 | HDWaitReq ENDP | ||
| 2222 | SUBTTL Routines that interface to floppy disk controller | ||
| 2223 | PAGE + | ||
| 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 | |||
| 2234 | GetDrivePtr PROC | ||
| 2235 | mov bx,cs:Floppy.Current | ||
| 2236 | add bx,bx | ||
| 2237 | mov bx,cs:FDinfo[bx] | ||
| 2238 | ret | ||
| 2239 | GetDrivePtr 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 | |||
| 2250 | GetFloppyParam 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 | ||
| 2263 | GetFloppyParam 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 | |||
| 2273 | Rcl765 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 | ||
| 2281 | Rcl765 ENDP | ||
| 2282 | |||
| 2283 | |||
| 2284 | ; Reset the controller. | ||
| 2285 | ; | ||
| 2286 | ; Destroys: AX,CX,DX | ||
| 2287 | ; | ||
| 2288 | |||
| 2289 | Rst765 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 | ||
| 2295 | RstDelayLoop: | ||
| 2296 | loop RstDelayLoop | ||
| 2297 | OR AL,DORmask | ||
| 2298 | MOV CS:Floppy.DOR,AL ; Update value | ||
| 2299 | OUT DX,AL | ||
| 2300 | RET | ||
| 2301 | Rst765 ENDP | ||
| 2302 | |||
| 2303 | |||
| 2304 | ; Load the drive specs into the controller. | ||
| 2305 | ; | ||
| 2306 | ; Destroys: AX,DX | ||
| 2307 | ; | ||
| 2308 | |||
| 2309 | Spec765 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 | ||
| 2319 | Spec765 ENDP | ||
| 2320 | |||
| 2321 | |||
| 2322 | ; Get the interrupt status from the controller and into AX | ||
| 2323 | ; | ||
| 2324 | ; Destroys: AX,CX,DX | ||
| 2325 | ; | ||
| 2326 | |||
| 2327 | Sense765 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 | ||
| 2338 | Sense765 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 | |||
| 2349 | Sel765 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 | ||
| 2356 | Sel765Double: | ||
| 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 | |||
| 2370 | SelectUnit: | ||
| 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 | |||
| 2388 | SelectStartMotor: | ||
| 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 | ||
| 2398 | Sel765 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 | |||
| 2407 | Seek765 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 | ||
| 2423 | SeekNoDouble: | ||
| 2424 | CALL Put765 ; Give controller the cylinder | ||
| 2425 | STC ; Set carry, must wait for seek intr. | ||
| 2426 | SeekDone: | ||
| 2427 | RET | ||
| 2428 | Seek765 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 | |||
| 2438 | RdWr765 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 | |||
| 2448 | WriteSetup: | ||
| 2449 | MOV AL,DMA_WRITE | ||
| 2450 | CALL DMAsetup ; Set DMA up for write | ||
| 2451 | MOV AL,FD_CWRITE ; Want to write | ||
| 2452 | RdWrLoc: | ||
| 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 | ||
| 2481 | RdWr765 ENDP | ||
| 2482 | |||
| 2483 | |||
| 2484 | |||
| 2485 | ; Fini765 gets the completion status. | ||
| 2486 | ; | ||
| 2487 | ; Destroys: AX,CX,DX | ||
| 2488 | ; Returns: AL | ||
| 2489 | ; | ||
| 2490 | |||
| 2491 | Fini765 PROC | ||
| 2492 | push es | ||
| 2493 | push di | ||
| 2494 | push cs | ||
| 2495 | pop es | ||
| 2496 | mov di,OFFSET Floppy.ST0 | ||
| 2497 | MOV CX,7 | ||
| 2498 | fini1: 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 | ||
| 2508 | Fini765 ENDP | ||
| 2509 | |||
| 2510 | |||
| 2511 | |||
| 2512 | ; Put765 writes a command to the controller. | ||
| 2513 | ; | ||
| 2514 | ; Input: AL = value | ||
| 2515 | ; Destroys: AX,DX | ||
| 2516 | ; | ||
| 2517 | |||
| 2518 | Put765 PROC | ||
| 2519 | PUSH AX ; Save the value to write | ||
| 2520 | PutWaitLoop: | ||
| 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 | ||
| 2530 | Put765 ENDP | ||
| 2531 | |||
| 2532 | |||
| 2533 | ; Get765 gets a value back from the controller into AL. | ||
| 2534 | ; | ||
| 2535 | ; Destroys: AX,DX | ||
| 2536 | ; Returns: AL | ||
| 2537 | ; | ||
| 2538 | |||
| 2539 | Get765 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 | ||
| 2548 | Get765 ENDP | ||
| 2549 | |||
| 2550 | Code 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 | |||
| 54 | FALSE EQU 0 | ||
| 55 | TRUE EQU NOT FALSE | ||
| 56 | |||
| 57 | CVERS equ 01 ; update version number!! | ||
| 58 | CREV equ 08 | ||
| 59 | |||
| 60 | BLANK equ TRUE ; blank screen during data r/w | ||
| 61 | INBIOS equ TRUE ; link with BIOS | ||
| 62 | ANSI equ TRUE ; include ANSI escape sequences | ||
| 63 | LINE25 equ TRUE ; special 25th line like VT52 | ||
| 64 | EAGLE equ TRUE ; Eagle PC ROM botches CRT_LEN | ||
| 65 | |||
| 66 | |||
| 67 | subttl Screen Information Block Definition | ||
| 68 | page | ||
| 69 | |||
| 70 | ;------------------------------------------------------------------------ | ||
| 71 | ; Screen Information Block (SIB) Definition | ||
| 72 | ; | ||
| 73 | ; This structure contains all information necessary to | ||
| 74 | ; describe the state of the screen, plus pointers to buffers | ||
| 75 | ; which contain the actual screen content. | ||
| 76 | ; | ||
| 77 | |||
| 78 | ;------------------------------------------------------------------------ | ||
| 79 | MaxSEG equ 2 ; NOTE: assumption is made in the | ||
| 80 | ; code that all SIB's have same | ||
| 81 | ; number os SEGs | ||
| 82 | SEGst struc | ||
| 83 | SizeNeeded dw 0 ; needed size for seg, (0 = unused) | ||
| 84 | MemFlag dw ? ; maintened by system (0 = in mem) | ||
| 85 | MPointer dd ? ; vaild iff MemFlag == 0 | ||
| 86 | SEGst ends | ||
| 87 | |||
| 88 | ;------------------------------------------------------------------------ | ||
| 89 | MaxSIB equ 8 ; maximum number of Screens | ||
| 90 | |||
| 91 | |||
| 92 | IF ANSI | ||
| 93 | TermSize EQU 20 ; max. size of terminal emulation state | ||
| 94 | ENDIF | ||
| 95 | |||
| 96 | SIBst struc | ||
| 97 | ctlS db 0 ; if the screen is NOT frozen = 0 | ||
| 98 | ; NOTE: this field should be the | ||
| 99 | ; FIRST of each SIB !! (see ConWrit) | ||
| 100 | OffsetVal dw 7 ; start of Seg Descriptors | ||
| 101 | SegCnt dw MaxSeg ; max number of Segments | ||
| 102 | SIBlen dw (SIZE SIBst) ; length of the SIB | ||
| 103 | ;--- Segments | ||
| 104 | db ((SIZE SEGst) * MaxSeg) dup (?) | ||
| 105 | ;--- PC video state info | ||
| 106 | xCRT_MODE DB ? | ||
| 107 | xCRT_COLS DW ? | ||
| 108 | xCRT_LEN DW ? | ||
| 109 | xCRT_START DW ? | ||
| 110 | xCURSOR_POSN DW 8 DUP(?) | ||
| 111 | xCURSOR_MODE DW ? | ||
| 112 | xACTIVE_PAGE DB ? | ||
| 113 | xADDR_6845 DW ? | ||
| 114 | xCRT_MODE_SET DB ? | ||
| 115 | xCRT_PALETTE DB ? | ||
| 116 | xTERM_STATE DB TermSize DUP(?) | ||
| 117 | SIBst ends | ||
| 118 | |||
| 119 | |||
| 120 | subttl Request packet definitions | ||
| 121 | page | ||
| 122 | |||
| 123 | ;------------------------------------------------------------------------ | ||
| 124 | ; Request packet offset definitions | ||
| 125 | ; | ||
| 126 | |||
| 127 | CMDLEN = 0 ;LENGTH OF THIS COMMAND | ||
| 128 | UNIT = 1 ;SUB UNIT SPECIFIER | ||
| 129 | CMD = 2 ;COMMAND CODE | ||
| 130 | STATUS = 3 ;STATUS | ||
| 131 | MEDIA = 13 ;MEDIA DESCRIPTOR | ||
| 132 | TRANS = 14 ;TRANSFER ADDRESS | ||
| 133 | COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS | ||
| 134 | START = 20 ;FIRST BLOCK TO TRANSFER | ||
| 135 | |||
| 136 | |||
| 137 | subttl IBM-PC ROM Data area Locations | ||
| 138 | page | ||
| 139 | |||
| 140 | ;------------------------------------------------------------------------ | ||
| 141 | ; IBM-PC ROM Data area Locations | ||
| 142 | ; | ||
| 143 | |||
| 144 | RomData SEGMENT AT 40H | ||
| 145 | ORG 1AH | ||
| 146 | BufferHead DW ? | ||
| 147 | BufferTail DW ? | ||
| 148 | KeyBuffer DW 16 DUP (?) | ||
| 149 | KeyBufLen equ ($-KeyBuffer) ; length of KeyBuffer | ||
| 150 | |||
| 151 | ORG 49H | ||
| 152 | CRT_MODE DB ? | ||
| 153 | CRT_COLS DW ? | ||
| 154 | CRT_LEN DW ? | ||
| 155 | CRT_START DW ? | ||
| 156 | CURSOR_POSN DW 8 DUP(?) | ||
| 157 | CURSOR_MODE DW ? | ||
| 158 | ACTIVE_PAGE DB ? | ||
| 159 | ADDR_6845 DW ? | ||
| 160 | CRT_MODE_SET DB ? | ||
| 161 | CRT_PALETTE DB ? | ||
| 162 | |||
| 163 | CrtLen EQU ($-CRT_MODE) ; length of screen state area | ||
| 164 | RomData ENDS | ||
| 165 | |||
| 166 | MonoSc SEGMENT AT 0B000H | ||
| 167 | ;--- 4k of screen memory | ||
| 168 | MonoSc ENDS | ||
| 169 | |||
| 170 | ColorSc SEGMENT AT 0B800H | ||
| 171 | ;--- 16k of screen memory | ||
| 172 | ColorSc ENDS | ||
| 173 | |||
| 174 | BRKADR equ 006CH ; Break vector address | ||
| 175 | |||
| 176 | |||
| 177 | subttl Device Header | ||
| 178 | page | ||
| 179 | |||
| 180 | |||
| 181 | BiosSeg group Code,BiosInit | ||
| 182 | Code Segment byte public 'CODE' | ||
| 183 | |||
| 184 | ;------------------------------------------------------------------------ | ||
| 185 | ; Device Header | ||
| 186 | ; | ||
| 187 | |||
| 188 | assume cs:Code,ds:NOTHING,es:NOTHING,ss:NOTHING | ||
| 189 | |||
| 190 | PUBLIC CONDEV | ||
| 191 | IF INBIOS | ||
| 192 | extrn AUXDEV:FAR | ||
| 193 | CONDEV dd AUXDEV | ||
| 194 | ELSE | ||
| 195 | CONDEV dw 0FFFFh,0FFFFh | ||
| 196 | ENDIF ;INBIOS | ||
| 197 | ;*** should ioctl bit be set for gen ioctl too? | ||
| 198 | dw 1100000000010011b ; console in and out | ||
| 199 | dw Strategy | ||
| 200 | dw Entry | ||
| 201 | db "CON " | ||
| 202 | |||
| 203 | |||
| 204 | ;------------------------------------------------------------------------ | ||
| 205 | ; Command dispatch table | ||
| 206 | ; | ||
| 207 | |||
| 208 | ComTbl: | ||
| 209 | ;--- 2.0 | ||
| 210 | dw OFFSET BiosSeg:$ConInit ; Initialization function | ||
| 211 | dw StatusComplete ; Media Check | ||
| 212 | dw StatusComplete ; Build BPB | ||
| 213 | dw CmdErr ; IOCTL Input | ||
| 214 | dw $ConRead ; Input (Read) | ||
| 215 | dw $ConRdnd ; Non-Destructive read, no wait | ||
| 216 | dw StatusComplete ; Input Status | ||
| 217 | dw $ConFlsh ; Input Flush | ||
| 218 | dw $ConWrit ; Output (Write) | ||
| 219 | dw $ConWrit ; Output with verify | ||
| 220 | dw StatusComplete ; Output Status | ||
| 221 | dw StatusComplete ; Output Flush | ||
| 222 | dw StatusComplete ; IOCTL Output | ||
| 223 | ;--- 3.0 | ||
| 224 | dw StatusComplete ; Device Open | ||
| 225 | dw StatusComplete ; Device Close | ||
| 226 | dw StatusComplete ; Removable Media | ||
| 227 | ;--- 4.0 | ||
| 228 | dw $GenIOCTL ; Generic IOCTL | ||
| 229 | dw $ConStop ; Pause Device | ||
| 230 | dw $ConStart ; Continue Device | ||
| 231 | |||
| 232 | ComTblEnd: | ||
| 233 | |||
| 234 | CTSIZE equ (ComTblEnd - ComTbl)/2 ; number of table entries | ||
| 235 | |||
| 236 | |||
| 237 | subttl Device Data Area | ||
| 238 | page | ||
| 239 | |||
| 240 | ;------------------------------------------------------------------------ | ||
| 241 | ; Device Data Area | ||
| 242 | ; | ||
| 243 | |||
| 244 | SaveFlg db 0 ; Screen being saved flag, (true = 1) | ||
| 245 | IF INBIOS | ||
| 246 | EXTRN DosFunction:DWORD | ||
| 247 | ELSE | ||
| 248 | DosFunction dd ? ; pointer to dos "helper" functions | ||
| 249 | ENDIF ;INBIOS | ||
| 250 | AltAH db 0 ; Side buffer for input | ||
| 251 | CurrSc dw 0 ; Current screen number | ||
| 252 | CurrSIB dw SIB ; offset to the current SIB | ||
| 253 | SIB SIBst MaxSIB dup (<>) ; allocate room for SIB's | ||
| 254 | |||
| 255 | IF EAGLE | ||
| 256 | ScreenLen db 08h ; table of (high byte of) regen. buffer | ||
| 257 | db 08h ; len. Indexed by screen mode. | ||
| 258 | db 10h ; 80x25 text modes | ||
| 259 | db 10h | ||
| 260 | db 40h ; graphics modes | ||
| 261 | db 40h | ||
| 262 | db 40h | ||
| 263 | db 10h ; monochrome | ||
| 264 | ENDIF | ||
| 265 | |||
| 266 | |||
| 267 | IFDEF DEBUGFLG | ||
| 268 | IF INBIOS | ||
| 269 | EXTRN BUGBITS:BYTE,DPRINTF:NEAR | ||
| 270 | ELSE | ||
| 271 | BUGBITS db 0ffh,0ffh | ||
| 272 | ENDIF | ||
| 273 | ENDIF | ||
| 274 | |||
| 275 | subttl Device Entry Points | ||
| 276 | page | ||
| 277 | |||
| 278 | ;------------------------------------------------------------------------ | ||
| 279 | ; 2.0 Interrupt Routine (Not Used) | ||
| 280 | ; | ||
| 281 | |||
| 282 | EntryP proc far | ||
| 283 | Entry: ret | ||
| 284 | EntryP endp | ||
| 285 | |||
| 286 | |||
| 287 | ;------------------------------------------------------------------------ | ||
| 288 | ; 2.0 Strategy Routine, main entry point | ||
| 289 | ; | ||
| 290 | ; entry | ||
| 291 | ; ES:BX points to Request packet | ||
| 292 | ; | ||
| 293 | |||
| 294 | StratP proc far | ||
| 295 | |||
| 296 | Strategy: | ||
| 297 | IF INBIOS | ||
| 298 | extrn Interrupt:NEAR | ||
| 299 | |||
| 300 | push si | ||
| 301 | mov si,OFFSET CS:ComTbl | ||
| 302 | jmp Interrupt | ||
| 303 | ELSE | ||
| 304 | push ax ; save all | ||
| 305 | push cx | ||
| 306 | push dx | ||
| 307 | push si | ||
| 308 | push di | ||
| 309 | push bp | ||
| 310 | push ds | ||
| 311 | |||
| 312 | push es ; DS = ES | ||
| 313 | pop ds | ||
| 314 | |||
| 315 | push es | ||
| 316 | push bx | ||
| 317 | mov al, byte ptr ds:[bx].CMD | ||
| 318 | cmp al,CTSIZE ; Command within range? | ||
| 319 | jae CmdErr ; no must be an error | ||
| 320 | mov cx, word ptr ds:[bx].COUNT | ||
| 321 | les di, dword ptr ds:[bx].TRANS | ||
| 322 | xor ah,ah | ||
| 323 | mov si, offset ComTbl | ||
| 324 | add si,ax | ||
| 325 | add si,ax | ||
| 326 | |||
| 327 | jmp word ptr cs:[si] ; dispatch | ||
| 328 | ENDIF ;INBIOS | ||
| 329 | |||
| 330 | StratP endp | ||
| 331 | |||
| 332 | |||
| 333 | subttl Exit Routines | ||
| 334 | page | ||
| 335 | |||
| 336 | ;------------------------------------------------------------------------ | ||
| 337 | ; Exit Routines, Common to all device functions | ||
| 338 | ; | ||
| 339 | |||
| 340 | IF INBIOS | ||
| 341 | extrn StatusComplete:NEAR,StatusError:NEAR,StatusDevReady:NEAR | ||
| 342 | extrn CmdErr:NEAR | ||
| 343 | ELSE | ||
| 344 | |||
| 345 | assume ds:NOTHING,es:NOTHING | ||
| 346 | |||
| 347 | StatusDevReady: | ||
| 348 | mov ah,00000011b ; device busy | ||
| 349 | jmp short errEx | ||
| 350 | |||
| 351 | CmdErr: | ||
| 352 | mov al,3 ; Unknown command Error | ||
| 353 | StatusError: | ||
| 354 | mov ah,10000001b | ||
| 355 | jmp short errEx | ||
| 356 | |||
| 357 | ExitP proc far | ||
| 358 | StatusComplete: mov ah,00000001b | ||
| 359 | errEx: pop bx | ||
| 360 | pop es | ||
| 361 | |||
| 362 | mov word ptr es:[bx].STATUS,ax ; put status out | ||
| 363 | |||
| 364 | pop ds | ||
| 365 | pop bp | ||
| 366 | pop di | ||
| 367 | pop si | ||
| 368 | pop dx | ||
| 369 | pop cx | ||
| 370 | pop ax | ||
| 371 | ret | ||
| 372 | ExitP endp | ||
| 373 | |||
| 374 | ENDIF ;INBIOS | ||
| 375 | |||
| 376 | |||
| 377 | subttl Break - Break interrupt routine | ||
| 378 | page | ||
| 379 | |||
| 380 | ;------------------------------------------------------------------------ | ||
| 381 | ; Break interrupt routine | ||
| 382 | ; | ||
| 383 | |||
| 384 | assume ds:NOTHING,es:NOTHING | ||
| 385 | |||
| 386 | Break PROC NEAR | ||
| 387 | int 32H ; save registers | ||
| 388 | cli ; ints should be off, make sure! | ||
| 389 | mov ax,RomData | ||
| 390 | mov ds,ax | ||
| 391 | assume ds:RomData | ||
| 392 | mov ax,offset RomData:KeyBuffer | ||
| 393 | mov [BufferHead],ax | ||
| 394 | mov [BufferTail],ax | ||
| 395 | assume ds:NOTHING | ||
| 396 | mov ax,3 ; send char to system | ||
| 397 | mov dx,5 ; ConsInputFilter subfunction | ||
| 398 | call [DosFunction] | ||
| 399 | jz brk1 ; key was eaten by system | ||
| 400 | mov [AltAH],al ; force a ^C | ||
| 401 | brk1: | ||
| 402 | iret | ||
| 403 | Break ENDP | ||
| 404 | |||
| 405 | SUBTTL Keyboard interrupt routine | ||
| 406 | PAGE | ||
| 407 | ; Replacement for ROM keyboard interrupt, tacks on the front. | ||
| 408 | ; OldKeyInterrupt is set to original contents of INT 09H. | ||
| 409 | ; The input character is passed to the O.S. console input filter | ||
| 410 | ; to determine if any special action should be taken. The filter | ||
| 411 | ; return value indicates if the character should be saved in the | ||
| 412 | ; type ahead buffer or if it should be discarded. A keyboard | ||
| 413 | ; semaphore exists to indicate if a process is waiting for input. | ||
| 414 | ; If the keboard semaphore is set all of the processes sleeping on | ||
| 415 | ; it are woken up. | ||
| 416 | |||
| 417 | OldKeyInterrupt DD ? | ||
| 418 | KeySem db 0 ; non-zero if someone waiting on input | ||
| 419 | |||
| 420 | KeyboardInterrupt PROC FAR | ||
| 421 | INT 32H ; Save regs | ||
| 422 | MOV AX,RomData | ||
| 423 | MOV DS,AX | ||
| 424 | ASSUME DS:RomData | ||
| 425 | |||
| 426 | PUSHF ; Save flags to simulate INT | ||
| 427 | CALL CS:OldKeyInterrupt ; Now do ROM code | ||
| 428 | ; Now tell DOS keyboard had char | ||
| 429 | cli ; interrupts off! | ||
| 430 | mov bx,BufferTail ; Get tail of queue | ||
| 431 | cmp bx,BufferHead ; Anything in keyboard queue? | ||
| 432 | JE NoKey ; No, don't requeue then | ||
| 433 | dec bx | ||
| 434 | dec bx | ||
| 435 | cmp bx,offset RomData:KeyBuffer | ||
| 436 | jae kbi1 ; no wrap around in buffer | ||
| 437 | mov bx,offset RomData:KeyBuffer+(KeyBufLen-2) | ||
| 438 | kbi1: | ||
| 439 | mov ax,[bx] ; get last queued char. | ||
| 440 | mov dx,5 ; ConsInputFilter subfunction | ||
| 441 | call [DosFunction] | ||
| 442 | jnz kbi2 ; key should remain in buffer | ||
| 443 | mov BufferTail,bx ; discard key from buffer | ||
| 444 | jmp SHORT NoKey | ||
| 445 | kbi2: | ||
| 446 | cli | ||
| 447 | CMP KeySem,0 ; Outstanding request? | ||
| 448 | JE NoKey ; No, may not be inited either | ||
| 449 | push ax | ||
| 450 | push bx | ||
| 451 | push cx | ||
| 452 | push dx | ||
| 453 | mov ax,cs | ||
| 454 | mov bx,OFFSET KeySem | ||
| 455 | mov cs:byte ptr [bx],0 ; reset keyboard semaphore | ||
| 456 | mov dx,10 ;; ProcRun | ||
| 457 | call [DosFunction] ; awaken anyone waiting on input | ||
| 458 | pop dx | ||
| 459 | pop cx | ||
| 460 | pop bx | ||
| 461 | pop ax | ||
| 462 | NoKey: | ||
| 463 | IRET | ||
| 464 | KeyBoardInterrupt ENDP | ||
| 465 | |||
| 466 | ;------------------------------------------------------------- | ||
| 467 | ; Keyboard INT 16 intercept routine to allow console input to sleep. | ||
| 468 | ; Only console input function 1 is intercepted, all other functions | ||
| 469 | ; are allowed to go directly to the ROM BIOS. For the function 1 | ||
| 470 | ; the input status is checked, if a character is ready the function | ||
| 471 | ; is allowed to go to the ROM BIOS. Otherwise the keyboard semaphore | ||
| 472 | ; is set and the process is put to sleep on the address of the | ||
| 473 | ; semaphore. When a key is typed the keyboard interrupt routine | ||
| 474 | ; will wakeup any processes sleeping on this semaphore. | ||
| 475 | ; | ||
| 476 | ; WARNING: The following routines can be entered recursively | ||
| 477 | ; due to the fact that the ROM BIOS routines called | ||
| 478 | ; reenable interrupts. It's not usually a problem | ||
| 479 | ; since interrupts will generally be processed faster | ||
| 480 | ; than anyone can type. | ||
| 481 | |||
| 482 | OldKbdHandler dd ? | ||
| 483 | ScrnIoOk dd ? | ||
| 484 | |||
| 485 | ;------------------------------------------------------------- | ||
| 486 | |||
| 487 | KeyBoardHandler proc far | ||
| 488 | or ah,ah | ||
| 489 | je DoLocalRead | ||
| 490 | cmp ah,1 | ||
| 491 | je DoLocalStat | ||
| 492 | OldKBint: | ||
| 493 | jmp [OldKbdHandler] | ||
| 494 | |||
| 495 | DoLocalStat: | ||
| 496 | push bx | ||
| 497 | push ds | ||
| 498 | lds bx,ScrnIoOk | ||
| 499 | test byte ptr [bx],0FFh | ||
| 500 | pop ds | ||
| 501 | pop bx | ||
| 502 | jnz OldKBint | ||
| 503 | xor ax,ax | ||
| 504 | ret 2 | ||
| 505 | DoInt16 LABEL FAR ; entry for ChrIn | ||
| 506 | DoLocalRead: | ||
| 507 | push ax | ||
| 508 | push bx | ||
| 509 | push cx | ||
| 510 | push dx | ||
| 511 | DoLocalRd1: | ||
| 512 | push ds | ||
| 513 | lds bx,ScrnIoOk | ||
| 514 | mov ax,ds | ||
| 515 | test byte ptr [bx],0FFh | ||
| 516 | pop ds | ||
| 517 | jnz DoLocalRd2 | ||
| 518 | xor cx,cx | ||
| 519 | mov dx,9 ;; ProcBlock | ||
| 520 | call [DosFunction] ; sleep until a screen switch | ||
| 521 | jmp DoLocalRd1 | ||
| 522 | |||
| 523 | DoLocalRd2: | ||
| 524 | mov ah,1 ; get console status | ||
| 525 | pushf ; simulate INT to old handler | ||
| 526 | cli | ||
| 527 | call [OldKbdHandler] | ||
| 528 | cli ; subfunction 1 unconditionally sets IF | ||
| 529 | jnz LocalRead ; go read character | ||
| 530 | mov ax,cs | ||
| 531 | mov bx,OFFSET KeySem | ||
| 532 | mov cs:byte ptr [bx],0FFh ; set keyboard semaphore | ||
| 533 | xor cx,cx | ||
| 534 | mov dx,9 ;; ProcBlock | ||
| 535 | call [DosFunction] ; sleep until a char is typed | ||
| 536 | jmp DoLocalRd1 | ||
| 537 | |||
| 538 | LocalRead: | ||
| 539 | pop dx | ||
| 540 | pop cx | ||
| 541 | pop bx | ||
| 542 | pop ax | ||
| 543 | jmp [OldKbdHandler] ; read the character and return | ||
| 544 | |||
| 545 | KeyBoardHandler endp | ||
| 546 | |||
| 547 | |||
| 548 | subttl $ConRead - Console Input (Read) | ||
| 549 | page | ||
| 550 | |||
| 551 | ;------------------------------------------------------------------------ | ||
| 552 | ; Console Input (Read) | ||
| 553 | ; | ||
| 554 | ; entry: | ||
| 555 | ; DS:BX = pointer to Request packet | ||
| 556 | ; ES:DI = Transfer address | ||
| 557 | ; CX = Count | ||
| 558 | ; | ||
| 559 | |||
| 560 | assume ds:NOTHING,es:NOTHING | ||
| 561 | |||
| 562 | $ConRead: | ||
| 563 | and cx,cx | ||
| 564 | jnz jgl2 | ||
| 565 | jmp CRExit | ||
| 566 | ; jcxz CRExit ; no chars to read BUGBUG restore | ||
| 567 | jgl2: cld ; make sure! | ||
| 568 | mov dx,word ptr ds:[bx].START ; get screen number | ||
| 569 | cmp dx,(MaxSIB-1) ; valid number? | ||
| 570 | jbe ConRLoop ; yes, do input | ||
| 571 | mov al,0BH ; no, READ FAULT ERROR | ||
| 572 | jmp StatusError | ||
| 573 | ConRLoop: | ||
| 574 | DEBUG 10h,1,<CONR:$x=$x? >,<dx,CurrSc> | ||
| 575 | cmp dx,[CurrSc] | ||
| 576 | je sjp0 | ||
| 577 | call GetSIBAdr ; get pointer to the SIB | ||
| 578 | DEBUG 10h,1,<Block read wrong screen >,<> | ||
| 579 | call DoPBlock ; block the process | ||
| 580 | jmp short ConRLoop ; test flag again | ||
| 581 | sjp0: | ||
| 582 | call ChrIn | ||
| 583 | stosb | ||
| 584 | ; loop ConRLoop | ||
| 585 | loop jgl3 | ||
| 586 | CRExit: jmp StatusComplete | ||
| 587 | |||
| 588 | jgl3: jmp ConRLoop | ||
| 589 | |||
| 590 | subttl ChrIn - Read a single character In | ||
| 591 | page | ||
| 592 | |||
| 593 | ;------------------------------------------------------------------------ | ||
| 594 | ; Read a single character In | ||
| 595 | ; | ||
| 596 | ; exit: | ||
| 597 | ; Character in AL | ||
| 598 | ; | ||
| 599 | ; modifies: AX | ||
| 600 | ; | ||
| 601 | |||
| 602 | assume ds:NOTHING,es:NOTHING | ||
| 603 | |||
| 604 | ChrIn: | ||
| 605 | DEBUG 10h,1,<in.ChrIn >,<> | ||
| 606 | xor ax,ax | ||
| 607 | xchg al,[AltAH] ; Get Character & zero AltAH | ||
| 608 | or al,al ; A char available? | ||
| 609 | jnz KeyRet | ||
| 610 | ; | ||
| 611 | ;--- NOTE: The blocking on read is done at int 16h level | ||
| 612 | ; in IBMBIO. No need to block here. | ||
| 613 | ; | ||
| 614 | DEBUG 10h,1,< con.do.16 >,<> | ||
| 615 | mov ah,0 ; no, do a read call | ||
| 616 | pushf | ||
| 617 | call DoInt16 | ||
| 618 | ;; int 16h | ||
| 619 | DEBUG 10h,1,< con.got.$x >,<ax> | ||
| 620 | or ax,ax ; check for non-key after BREAK | ||
| 621 | jnz jgl1 | ||
| 622 | jmp chrin | ||
| 623 | |||
| 624 | jgl1: cmp ax,7200h ; CTRL-PRTSC ? | ||
| 625 | jnz sja0 | ||
| 626 | mov al,10h ; yes, make it a ctrl-P | ||
| 627 | sja0: or al,al ; special case? | ||
| 628 | jnz KeyRet | ||
| 629 | mov [AltAH],ah | ||
| 630 | KeyRet: | ||
| 631 | ret | ||
| 632 | |||
| 633 | |||
| 634 | subttl $ConRdnd - Console non-destructive Input, no wait | ||
| 635 | page | ||
| 636 | |||
| 637 | ;------------------------------------------------------------------------ | ||
| 638 | ; Console non-destructive Input, no wait | ||
| 639 | ; | ||
| 640 | ; entry: | ||
| 641 | ; DS:BX = pointer to Request packet | ||
| 642 | ; | ||
| 643 | |||
| 644 | assume ds:NOTHING,es:NOTHING | ||
| 645 | |||
| 646 | $ConRdnd: | ||
| 647 | mov dx,word ptr ds:[bx].START ; get screen number | ||
| 648 | cmp dx,(MaxSIB-1) ; valid number? | ||
| 649 | jbe sjq0 ; yes, do input | ||
| 650 | mov al,0BH ; no, READ FAULT ERROR | ||
| 651 | jmp StatusError | ||
| 652 | sjq0: | ||
| 653 | DEBUG 10h,1,<CNDR:$x=$x? >,<dx,CurrSc> | ||
| 654 | cmp dx,[CurrSc] | ||
| 655 | IFDEF DEBUGFLG | ||
| 656 | je sjq1 | ||
| 657 | jmp ConBus | ||
| 658 | ELSE | ||
| 659 | jne ConBus ; not current screen, no char avail | ||
| 660 | ENDIF | ||
| 661 | ; call GetSIBAdr ; get pointer to the SIB | ||
| 662 | ; call DoPBlock ; block the process | ||
| 663 | ; jmp short sjq0 ; test flag again | ||
| 664 | sjq1: | ||
| 665 | mov al,[AltAH] ; char avail already? | ||
| 666 | or al,al | ||
| 667 | jnz rdExit | ||
| 668 | DEBUG 10h,1,< NRD:do.16 >,<> | ||
| 669 | mov ah,1 ; no, get status | ||
| 670 | int 16h | ||
| 671 | jz ConBus | ||
| 672 | DEBUG 10h,1,< NRD:nonbus $x >,<ax> | ||
| 673 | or ax,ax | ||
| 674 | jnz NotBk ; Check for null after break | ||
| 675 | mov ah,0 ; flush the null | ||
| 676 | int 16h | ||
| 677 | jmp $ConRdnd ; try again | ||
| 678 | ; jmp short $ConRdnd ; try again BUGBUG | ||
| 679 | NotBk: | ||
| 680 | cmp ax,7200h ; CTRL-PRTSC ? | ||
| 681 | jnz rdExit | ||
| 682 | mov al,10h ; yes, make it a ctrl-P | ||
| 683 | rdExit: | ||
| 684 | mov byte ptr ds:[bx].MEDIA,al ; save character | ||
| 685 | DoExit: jmp StatusComplete | ||
| 686 | |||
| 687 | ConBus: DEBUG 10h,1,< ConBus - >,<> | ||
| 688 | jmp StatusDevReady | ||
| 689 | |||
| 690 | |||
| 691 | subttl $ConFlsh - Console Flush Input | ||
| 692 | page | ||
| 693 | |||
| 694 | ;------------------------------------------------------------------------ | ||
| 695 | ; Console Flush Input | ||
| 696 | ; | ||
| 697 | ; entry: | ||
| 698 | ; DS:BX = pointer to Request packet | ||
| 699 | ; | ||
| 700 | |||
| 701 | assume ds:NOTHING,es:NOTHING | ||
| 702 | |||
| 703 | $ConFlsh: | ||
| 704 | mov dx,word ptr ds:[bx].START ; get screen number | ||
| 705 | cmp dx,(MaxSIB-1) ; valid number? | ||
| 706 | jbe sjr0 ; yes, do flush | ||
| 707 | mov al,0BH ; no, READ FAULT ERROR | ||
| 708 | jmp StatusError | ||
| 709 | sjr0: | ||
| 710 | cmp dx,[CurrSc] | ||
| 711 | je sjr1 | ||
| 712 | call GetSIBAdr ; get pointer to the SIB | ||
| 713 | call DoPBlock ; block the process | ||
| 714 | jmp short sjr0 ; test flag again | ||
| 715 | sjr1: | ||
| 716 | mov [AltAH],0 ; clear side bufer | ||
| 717 | push ds | ||
| 718 | mov ax,RomData | ||
| 719 | mov ds,ax | ||
| 720 | assume ds:RomData | ||
| 721 | cli ; Disable interrupts | ||
| 722 | mov ax,offset RomData:KeyBuffer ; Start of Rom buffer | ||
| 723 | mov [BufferHead],ax | ||
| 724 | mov [BufferTail],ax ; Empty the queue | ||
| 725 | sti | ||
| 726 | pop ds | ||
| 727 | assume ds:NOTHING | ||
| 728 | jmp StatusComplete | ||
| 729 | |||
| 730 | |||
| 731 | subttl $ConWrit - Console Output (Write) | ||
| 732 | page | ||
| 733 | |||
| 734 | ;------------------------------------------------------------------------ | ||
| 735 | ; Console Output (Write) | ||
| 736 | ; | ||
| 737 | ; entry: | ||
| 738 | ; DS:BX = pointer to Request packet | ||
| 739 | ; ES:DI = Transfer address | ||
| 740 | ; CX = Count | ||
| 741 | ; | ||
| 742 | |||
| 743 | assume ds:NOTHING,es:NOTHING | ||
| 744 | |||
| 745 | $ConWrit: | ||
| 746 | jcxz CWExit | ||
| 747 | mov dx, word ptr ds:[bx].START ; get screen number | ||
| 748 | cmp dx,(MaxSIB-1) ; valid screen number? | ||
| 749 | jbe sjb0 | ||
| 750 | mov al,0AH ; no, write fault error | ||
| 751 | jmp StatusError | ||
| 752 | sjb0: push cs | ||
| 753 | pop ds | ||
| 754 | assume ds:Code | ||
| 755 | mov bx,[CurrSIB] | ||
| 756 | |||
| 757 | ConWLoop: | ||
| 758 | cmp dx,[CurrSc] ; Is it to the current screen? | ||
| 759 | je sjb2 ; yes, do not block | ||
| 760 | call GetSIBAdr ; get pointer to the SIB | ||
| 761 | sjb1: call DoPBlock ; block the process | ||
| 762 | jmp short ConWLoop ; test ALL flags again | ||
| 763 | sjb2: | ||
| 764 | cmp [bx].ctlS,0 ; is the screen frozen? | ||
| 765 | je sjb3 | ||
| 766 | mov ax,bx ; AX = [CurrSIB] = [CurrSIB].ctlS !!!! | ||
| 767 | jmp short sjb1 ; yes, block the process | ||
| 768 | sjb3: | ||
| 769 | cmp [SaveFlg],0 ; are we in the middle of a save? | ||
| 770 | je sjb4 ; no, do write | ||
| 771 | mov ax,offset SaveFlg | ||
| 772 | jmp short sjb1 ; yes, block... | ||
| 773 | sjb4: | ||
| 774 | mov al,es:[di] ; get a character | ||
| 775 | inc di | ||
| 776 | call CharOut | ||
| 777 | loop ConWLoop | ||
| 778 | CWExit: jmp StatusComplete | ||
| 779 | |||
| 780 | |||
| 781 | subttl CharOut - Output a character to the screen | ||
| 782 | page | ||
| 783 | |||
| 784 | ;------------------------------------------------------------------------ | ||
| 785 | ; Output a character to the screen | ||
| 786 | ; | ||
| 787 | ; entry: | ||
| 788 | ; AL = Character to write | ||
| 789 | ; | ||
| 790 | ; preserves: | ||
| 791 | ; BX, CX, DX, DI, DS & ES | ||
| 792 | ; | ||
| 793 | |||
| 794 | assume ds:NOTHING,es:NOTHING | ||
| 795 | |||
| 796 | IF ANSI | ||
| 797 | include ansi.inc | ||
| 798 | ELSE | ||
| 799 | CharOut: | ||
| 800 | push bx | ||
| 801 | push di | ||
| 802 | mov bx,7 | ||
| 803 | mov ah,14 | ||
| 804 | int 10h ; Write Character | ||
| 805 | pop di | ||
| 806 | pop bx | ||
| 807 | ret | ||
| 808 | ENDIF | ||
| 809 | |||
| 810 | |||
| 811 | subttl $GenIOCTL - Generic IOCTL | ||
| 812 | page | ||
| 813 | |||
| 814 | ;------------------------------------------------------------------------ | ||
| 815 | ; Generic IOCTL | ||
| 816 | ; | ||
| 817 | ; entry: | ||
| 818 | ; DS:BX = pointer to Request packet | ||
| 819 | ; | ||
| 820 | |||
| 821 | ;--- Offsets into the request packet | ||
| 822 | ;*** Check offset are correct | ||
| 823 | FunCode = 14 ; Function Code | ||
| 824 | FunCat = 13 ; Function Category | ||
| 825 | ;*** | ||
| 826 | RegSI = 15 ; Contents of SI | ||
| 827 | RegDI = 17 ; Contents of DI | ||
| 828 | DatBuf = 19 ; Pointer to data buffer | ||
| 829 | |||
| 830 | ;--- Code & Category definitions | ||
| 831 | IOC_SC = 03h ;--- Screen Control | ||
| 832 | IOSC_LS = 41h ; Locate SIB | ||
| 833 | IOSC_SS = 42h ; save segment | ||
| 834 | IOSC_RS = 43h ; restore segment | ||
| 835 | IOSC_EI = 44h ; re-enable i/o | ||
| 836 | IOSC_IS = 45h ; initialize screen | ||
| 837 | |||
| 838 | assume ds:NOTHING,es:NOTHING | ||
| 839 | |||
| 840 | $GenIOCTL: | ||
| 841 | cmp byte ptr ds:[bx].FunCode,IOC_SC | ||
| 842 | jne GI_BadCode ; function not suported | ||
| 843 | mov si,word ptr ds:[bx].RegSI | ||
| 844 | mov al,byte ptr ds:[bx].FunCat | ||
| 845 | cmp al,IOSC_LS | ||
| 846 | jne sjc0 | ||
| 847 | jmp short do_IOSC_LS | ||
| 848 | sjc0: cmp al,IOSC_SS | ||
| 849 | jne sjc1 | ||
| 850 | jmp short do_IOSC_SS | ||
| 851 | sjc1: cmp al,IOSC_RS | ||
| 852 | jne sjc2 | ||
| 853 | jmp do_IOSC_RS | ||
| 854 | sjc2: cmp al,IOSC_EI | ||
| 855 | jne sjc3 | ||
| 856 | jmp do_IOSC_EI | ||
| 857 | sjc3: cmp al,IOSC_IS | ||
| 858 | jne GI_BadCode | ||
| 859 | jmp do_IOSC_IS | ||
| 860 | |||
| 861 | GI_BadCode: | ||
| 862 | jmp CmdErr ; error exit: Command error | ||
| 863 | |||
| 864 | |||
| 865 | subttl do_IOSC_LS - Locate SIB | ||
| 866 | page | ||
| 867 | |||
| 868 | ;------------------------------------------------------------------------ | ||
| 869 | ; Locate SIB | ||
| 870 | ; | ||
| 871 | ; entry: | ||
| 872 | ; SI = SIB Number | ||
| 873 | ; DS:BX = pointer to Request packet | ||
| 874 | ; | ||
| 875 | |||
| 876 | assume ds:NOTHING,es:NOTHING | ||
| 877 | |||
| 878 | do_IOSC_LS: | ||
| 879 | cmp si,(MaxSIB-1) ; index within range? | ||
| 880 | ja BadNum | ||
| 881 | push bx | ||
| 882 | push ds | ||
| 883 | push cs | ||
| 884 | pop ds | ||
| 885 | assume ds:Code | ||
| 886 | cmp si,[CurrSc] ; is it the current screen? | ||
| 887 | je CurrLS | ||
| 888 | mov [CurrSc],si ; no, just switch curr screens | ||
| 889 | mov dx,si ; index | ||
| 890 | call GetSIBAdr ; get pointer to SIB | ||
| 891 | mov [CurrSIB],ax ; save pointer to curr SIB | ||
| 892 | jmp short retLS | ||
| 893 | |||
| 894 | CurrLS: | ||
| 895 | mov [SaveFlg],1 ; Signal we are Saving the screen | ||
| 896 | |||
| 897 | ;*** Only one segment for now | ||
| 898 | |||
| 899 | mov ax,0 | ||
| 900 | call GetSegAdr ; on return BX points to segment | ||
| 901 | mov ax,RomData | ||
| 902 | mov es,ax | ||
| 903 | assume es:RomData | ||
| 904 | IF EAGLE | ||
| 905 | mov al,es:[CRT_MODE] | ||
| 906 | xor ah,ah | ||
| 907 | mov si,ax | ||
| 908 | mov ah,ScreenLen[si] | ||
| 909 | xor al,al | ||
| 910 | ELSE | ||
| 911 | mov ax,es:[CRT_LEN] | ||
| 912 | assume es:NOTHING ; not true, but just to be safe | ||
| 913 | ENDIF | ||
| 914 | mov [bx].SizeNeeded,ax ; save size of segment | ||
| 915 | mov ax,dx ; pointer to current SIB | ||
| 916 | retLS: | ||
| 917 | pop ds | ||
| 918 | pop bx | ||
| 919 | assume ds:NOTHING | ||
| 920 | mov word ptr ds:[bx].DatBuf,ax ; offset | ||
| 921 | mov word ptr ds:[bx].DatBuf+2,cs ; segment | ||
| 922 | mov word ptr ds:[bx].RegSI,0 ; operation ok | ||
| 923 | jmp StatusComplete | ||
| 924 | |||
| 925 | BadNum: | ||
| 926 | mov word ptr ds:[bx].RegSI,1 ; bad SIB number error | ||
| 927 | jmp StatusComplete | ||
| 928 | |||
| 929 | |||
| 930 | subttl do_IOSC_SS - Save Segment | ||
| 931 | page | ||
| 932 | |||
| 933 | ;------------------------------------------------------------------------ | ||
| 934 | ; Save Segment | ||
| 935 | ; | ||
| 936 | ; entry: | ||
| 937 | ; SI = Segment Index (into the Current SIB) | ||
| 938 | ; DS:BX = pointer to Request packet | ||
| 939 | ; | ||
| 940 | |||
| 941 | assume ds:NOTHING,es:NOTHING | ||
| 942 | |||
| 943 | do_IOSC_SS: | ||
| 944 | cmp si,(MaxSeg-1) ; within range? | ||
| 945 | BadNumJ1: | ||
| 946 | ja BadNum ; no, somebody screwed up... | ||
| 947 | push bx | ||
| 948 | push ds | ||
| 949 | cmp si,0 ; first segment save? | ||
| 950 | jne nfSS ; no, just save screen data | ||
| 951 | ;--- save screen state data | ||
| 952 | push si ; save index | ||
| 953 | mov ax,RomData | ||
| 954 | mov ds,ax ; DS = ROM data area | ||
| 955 | assume ds:RomData | ||
| 956 | mov si,offset RomData:CRT_MODE | ||
| 957 | mov cx,CrtLen ; length of screen state data | ||
| 958 | push cs | ||
| 959 | pop es | ||
| 960 | assume es:Code | ||
| 961 | mov di,[CurrSIB] | ||
| 962 | lea di,[di].xCRT_MODE | ||
| 963 | cld | ||
| 964 | rep movsb ; copy ROM info to SIB area | ||
| 965 | IF ANSI | ||
| 966 | push cs | ||
| 967 | pop ds | ||
| 968 | assume ds:Code | ||
| 969 | mov si,offset AnsiState ; point to ANSI state info | ||
| 970 | mov cx,AnsiSize | ||
| 971 | rep movsb ; save ANSI state info in SIB | ||
| 972 | ENDIF | ||
| 973 | pop si ; restore segment index | ||
| 974 | ;--- save a segment of screen data | ||
| 975 | nfSS: | ||
| 976 | push cs | ||
| 977 | pop ds | ||
| 978 | assume ds:Code | ||
| 979 | mov ax,si | ||
| 980 | call GetSegAdr ; get adress of segment and curr SIB ptr | ||
| 981 | mov cx,[bx].SizeNeeded ; CX = Ammount to transfer | ||
| 982 | shr cx,1 ; words! | ||
| 983 | les di,[bx].MPointer ; ES:DI = Screen save area | ||
| 984 | assume es:NOTHING | ||
| 985 | |||
| 986 | ;*** For now we are using only one segment | ||
| 987 | |||
| 988 | mov si,dx ; SI points to the current SIB | ||
| 989 | mov bx,ColorSc ; assume color card | ||
| 990 | cmp [si].xCRT_MODE,7 ; is this a BW monitor? | ||
| 991 | jne do_save | ||
| 992 | mov bx,MonoSc | ||
| 993 | do_save: | ||
| 994 | IF BLANK | ||
| 995 | mov dx,[si].xADDR_6845 ; point to mode register | ||
| 996 | add dx,4 | ||
| 997 | mov al,[si].xCRT_MODE_SET ; and get value | ||
| 998 | and al,NOT 8 | ||
| 999 | out dx,al ; turn off video | ||
| 1000 | ENDIF | ||
| 1001 | mov ds,bx ; DS points to apropiate screen area | ||
| 1002 | assume ds:NOTHING | ||
| 1003 | mov si,0 | ||
| 1004 | cld | ||
| 1005 | rep movsw ; copy the screen | ||
| 1006 | IF BLANK | ||
| 1007 | or al,8 | ||
| 1008 | out dx,al ; turn on video | ||
| 1009 | ENDIF | ||
| 1010 | pop ds | ||
| 1011 | pop bx | ||
| 1012 | mov word ptr ds:[bx].RegSI,0 ; operation ok | ||
| 1013 | jmp StatusComplete | ||
| 1014 | |||
| 1015 | |||
| 1016 | subttl do_IOSC_RS - Restore Segment | ||
| 1017 | page | ||
| 1018 | |||
| 1019 | ;------------------------------------------------------------------------ | ||
| 1020 | ; Restore Segment | ||
| 1021 | ; | ||
| 1022 | ; entry: | ||
| 1023 | ; SI = Segment Index (into the Current SIB) | ||
| 1024 | ; DS:BX = pointer to Request packet | ||
| 1025 | ; | ||
| 1026 | |||
| 1027 | assume ds:NOTHING,es:NOTHING | ||
| 1028 | |||
| 1029 | do_IOSC_RS: | ||
| 1030 | cmp si,(MaxSeg-1) ; within range? | ||
| 1031 | ja BadNumJ1 ; no, somebody screwed up... | ||
| 1032 | push bx | ||
| 1033 | push ds | ||
| 1034 | push cs | ||
| 1035 | pop ds | ||
| 1036 | assume ds:Code | ||
| 1037 | cmp si,0 ; first segment save? | ||
| 1038 | jne nfRS ; no, just restore screen data | ||
| 1039 | ;--- restore screen state data | ||
| 1040 | push si ; save index | ||
| 1041 | mov si,[CurrSIB] | ||
| 1042 | push si | ||
| 1043 | lea si,[si].xCRT_MODE | ||
| 1044 | mov ax,RomData | ||
| 1045 | mov es,ax ; ES = ROM data area | ||
| 1046 | assume es:RomData | ||
| 1047 | mov cx,CrtLen ; length of screen state data | ||
| 1048 | mov di,offset RomData:CRT_MODE | ||
| 1049 | cld | ||
| 1050 | rep movsb ; copy ROM info from SIB area | ||
| 1051 | IF ANSI | ||
| 1052 | push es | ||
| 1053 | push cs | ||
| 1054 | pop es | ||
| 1055 | assume es:Code | ||
| 1056 | mov di,offset AnsiState ; point to ANSI state info | ||
| 1057 | mov cx,AnsiSize | ||
| 1058 | rep movsb ; restore ANSI state info from SIB | ||
| 1059 | pop es | ||
| 1060 | assume es:RomData | ||
| 1061 | ENDIF | ||
| 1062 | |||
| 1063 | ;--- Setup new screen state | ||
| 1064 | pop si | ||
| 1065 | mov al,[si].xCRT_MODE | ||
| 1066 | cmp al,7 ; is this the BW monitor? | ||
| 1067 | jne sjd0 | ||
| 1068 | mov al,2 ; this is the "real" mode | ||
| 1069 | sjd0: | ||
| 1070 | mov ah,0 | ||
| 1071 | int 10h ; set new mode | ||
| 1072 | mov cx,[si].xCURSOR_MODE | ||
| 1073 | mov ah,1 | ||
| 1074 | int 10h ; set cursor type | ||
| 1075 | mov dx,[si].xCURSOR_POSN | ||
| 1076 | mov bh,[si].xACTIVE_PAGE | ||
| 1077 | mov ah,2 | ||
| 1078 | int 10h ; set cursor position | ||
| 1079 | mov al,[si].xACTIVE_PAGE | ||
| 1080 | mov ah,5 | ||
| 1081 | int 10h ; set page # | ||
| 1082 | mov dx,[si].xADDR_6845 | ||
| 1083 | add dx,5 | ||
| 1084 | mov al,[si].xCRT_PALETTE | ||
| 1085 | out dx,al ; set color port | ||
| 1086 | mov es:CRT_PALETTE,al | ||
| 1087 | pop si ; restore segment index | ||
| 1088 | ;--- restore a segment of screen data | ||
| 1089 | nfRS: | ||
| 1090 | mov ax,si | ||
| 1091 | call GetSegAdr ; get adress of segment | ||
| 1092 | mov cx,[bx].SizeNeeded ; CX = Ammount to transfer | ||
| 1093 | shr cx,1 ; words! | ||
| 1094 | lds si,[bx].MPointer ; DS:SI = Screen save area | ||
| 1095 | assume ds:NOTHING | ||
| 1096 | |||
| 1097 | ;*** For now we are using only one segment | ||
| 1098 | |||
| 1099 | mov di,dx ; DI points to the current SIB | ||
| 1100 | mov bx,ColorSc ; assume color card | ||
| 1101 | cmp cs:[di].xCRT_MODE,7 ; is this a BW monitor? | ||
| 1102 | jne do_rest | ||
| 1103 | mov bx,MonoSc | ||
| 1104 | do_rest: | ||
| 1105 | IF BLANK | ||
| 1106 | mov dx,cs:[di].xADDR_6845 ; point to mode register | ||
| 1107 | add dx,4 | ||
| 1108 | mov al,cs:[di].xCRT_MODE_SET ; and get value | ||
| 1109 | and al,NOT 8 | ||
| 1110 | out dx,al ; turn off video | ||
| 1111 | ENDIF | ||
| 1112 | mov es,bx ; ES points to apropiate screen area | ||
| 1113 | assume es:NOTHING | ||
| 1114 | mov di,0 | ||
| 1115 | cld | ||
| 1116 | rep movsw ; copy the screen | ||
| 1117 | IF BLANK | ||
| 1118 | or al,8 | ||
| 1119 | out dx,al ; turn on video | ||
| 1120 | ENDIF | ||
| 1121 | |||
| 1122 | pop ds | ||
| 1123 | assume ds:NOTHING | ||
| 1124 | pop bx | ||
| 1125 | mov word ptr ds:[bx].RegSI,0 ; operation ok | ||
| 1126 | jmp StatusComplete | ||
| 1127 | |||
| 1128 | BadNumJ: | ||
| 1129 | jmp BadNum | ||
| 1130 | |||
| 1131 | |||
| 1132 | subttl do_IOSC_EI - Re-enable i/o | ||
| 1133 | page | ||
| 1134 | |||
| 1135 | ;------------------------------------------------------------------------ | ||
| 1136 | ; Re-enable i/o | ||
| 1137 | ; | ||
| 1138 | ; entry: | ||
| 1139 | ; DS:BX = pointer to Request packet | ||
| 1140 | ; | ||
| 1141 | |||
| 1142 | assume ds:NOTHING,es:NOTHING | ||
| 1143 | |||
| 1144 | do_IOSC_EI: | ||
| 1145 | mov [SaveFlg],0 ; Signal we are done Saving the screen | ||
| 1146 | mov ax,offset Code:SaveFlg | ||
| 1147 | call DoPRun ; ProcRun | ||
| 1148 | mov ax,[CurrSIB] ; pointer to current SIB | ||
| 1149 | call DoPRun ; ProcRun any output blocked because | ||
| 1150 | ; screen was not current | ||
| 1151 | jmp StatusComplete | ||
| 1152 | |||
| 1153 | |||
| 1154 | subttl do_IOSC_IS - Initialize Screen | ||
| 1155 | page | ||
| 1156 | |||
| 1157 | ;------------------------------------------------------------------------ | ||
| 1158 | ; Initialize Screen | ||
| 1159 | ; | ||
| 1160 | ; entry: | ||
| 1161 | ; SI = SIB Number | ||
| 1162 | ; DS:BX = pointer to Request packet | ||
| 1163 | ; | ||
| 1164 | |||
| 1165 | assume ds:NOTHING,es:NOTHING | ||
| 1166 | |||
| 1167 | do_IOSC_IS: | ||
| 1168 | cmp si,(MaxSIB-1) ; index within range? | ||
| 1169 | ja BadNumJ | ||
| 1170 | push ds | ||
| 1171 | push cs | ||
| 1172 | pop ds | ||
| 1173 | assume ds:Code | ||
| 1174 | mov [CurrSc],si ; switch curr screens | ||
| 1175 | mov dx,si ; index | ||
| 1176 | call GetSIBAdr ; get pointer to SIB | ||
| 1177 | mov [CurrSIB],ax ; save pointer to curr SIB | ||
| 1178 | mov si,ax | ||
| 1179 | mov [si].ctlS,0 ; screen not frozen | ||
| 1180 | ;--- set screen mode to pc mode 3 (80x25 BW) | ||
| 1181 | mov ax,0003 ; Set mode 3 | ||
| 1182 | int 10h | ||
| 1183 | pop ds | ||
| 1184 | assume ds:NOTHING | ||
| 1185 | mov word ptr ds:[bx].RegSI,0 ; operation ok | ||
| 1186 | jmp StatusComplete | ||
| 1187 | |||
| 1188 | |||
| 1189 | subttl $ConStop - Stop (freeze) console output | ||
| 1190 | page | ||
| 1191 | |||
| 1192 | ;------------------------------------------------------------------------ | ||
| 1193 | ; Stop (freeze) console output | ||
| 1194 | ; | ||
| 1195 | |||
| 1196 | assume ds:NOTHING,es:NOTHING | ||
| 1197 | |||
| 1198 | $ConStop: | ||
| 1199 | mov bx,[CurrSIB] ; pointer to current SIB | ||
| 1200 | mov cs:[bx].ctlS,01 ; set the freeze flag | ||
| 1201 | jmp StatusComplete | ||
| 1202 | |||
| 1203 | |||
| 1204 | subttl $ConStart - Start (continue) console output | ||
| 1205 | page | ||
| 1206 | |||
| 1207 | ;------------------------------------------------------------------------ | ||
| 1208 | ; Start (continue) console output | ||
| 1209 | ; | ||
| 1210 | |||
| 1211 | assume ds:NOTHING,es:NOTHING | ||
| 1212 | |||
| 1213 | $ConStart: | ||
| 1214 | mov bx,[CurrSIB] ; pointer to current SIB | ||
| 1215 | cmp cs:[bx].ctlS,0 ; is it already going? | ||
| 1216 | je csRet ; yes, no need to re-enable | ||
| 1217 | mov cs:[bx].ctlS,0 ; reset the freeze flag | ||
| 1218 | lea ax,[bx].ctlS ; get address of current ctlS | ||
| 1219 | call DoPRun ; do ProcRun | ||
| 1220 | csRet: jmp StatusComplete | ||
| 1221 | |||
| 1222 | |||
| 1223 | subttl DoPBlock - Block the current process | ||
| 1224 | page | ||
| 1225 | |||
| 1226 | ;------------------------------------------------------------------------ | ||
| 1227 | ; Block the current process | ||
| 1228 | ; | ||
| 1229 | ; entry: | ||
| 1230 | ; CS:AX = address to block on | ||
| 1231 | ; | ||
| 1232 | ; modifies: AX, FLAGS | ||
| 1233 | ; | ||
| 1234 | |||
| 1235 | assume ds:NOTHING,es:NOTHING | ||
| 1236 | |||
| 1237 | DoPBlock: | ||
| 1238 | push bx | ||
| 1239 | push cx | ||
| 1240 | push dx | ||
| 1241 | mov bx,ax | ||
| 1242 | mov ax,cs ; AX:BX = event identifier | ||
| 1243 | xor cx,cx ; No timeout | ||
| 1244 | ;; mov dx,0109h ;;BUGBUG - should be interruptible wait; will | ||
| 1245 | ;; give InternalError (SchedFind - not on Q) | ||
| 1246 | mov dx,0009h ; PROCBLOC function | ||
| 1247 | cli ; No races! | ||
| 1248 | call [DosFunction] | ||
| 1249 | pop dx ; on return ints are back on | ||
| 1250 | pop cx | ||
| 1251 | pop bx | ||
| 1252 | ret | ||
| 1253 | |||
| 1254 | |||
| 1255 | subttl DoPRun - Restart a process | ||
| 1256 | page | ||
| 1257 | |||
| 1258 | ;------------------------------------------------------------------------ | ||
| 1259 | ; Restart a process | ||
| 1260 | ; | ||
| 1261 | ; entry: | ||
| 1262 | ; CS:AX = address to signal on (same as blocked on) | ||
| 1263 | ; | ||
| 1264 | ; modifies: AX, FLAGS | ||
| 1265 | ; | ||
| 1266 | |||
| 1267 | assume ds:NOTHING,es:NOTHING | ||
| 1268 | |||
| 1269 | DoPRun: | ||
| 1270 | push bx | ||
| 1271 | push cx | ||
| 1272 | push dx | ||
| 1273 | mov bx,ax | ||
| 1274 | mov ax,cs | ||
| 1275 | mov dx,10 ; PROCRUN function | ||
| 1276 | call [DosFunction] | ||
| 1277 | pop dx | ||
| 1278 | pop cx | ||
| 1279 | pop bx | ||
| 1280 | ret | ||
| 1281 | |||
| 1282 | |||
| 1283 | subttl GetSIBAdr - Return SIB address | ||
| 1284 | page | ||
| 1285 | |||
| 1286 | ;------------------------------------------------------------------------ | ||
| 1287 | ; Returns the adress of the specified SIB | ||
| 1288 | ; | ||
| 1289 | ; entry: | ||
| 1290 | ; DX = index to the SIB | ||
| 1291 | ; | ||
| 1292 | ; exit: | ||
| 1293 | ; AX = pointer to the SIB | ||
| 1294 | ; | ||
| 1295 | ; preserves: ALL | ||
| 1296 | ; | ||
| 1297 | |||
| 1298 | assume ds:Code,es:NOTHING | ||
| 1299 | |||
| 1300 | GetSIBAdr: | ||
| 1301 | push dx ; save screen # | ||
| 1302 | mov ax,dx ; index | ||
| 1303 | mov dx,(SIZE SIBst) | ||
| 1304 | mul dx ; multiply by size of SIB entry | ||
| 1305 | pop dx ; restore screen # | ||
| 1306 | add ax,offset SIB ; AX = pointer to SIB for the write | ||
| 1307 | ret | ||
| 1308 | |||
| 1309 | |||
| 1310 | subttl GetSegAdr - Return segment address | ||
| 1311 | page | ||
| 1312 | |||
| 1313 | ;------------------------------------------------------------------------ | ||
| 1314 | ; Returns the adress of a segment in the current SIB | ||
| 1315 | ; | ||
| 1316 | ; entry: | ||
| 1317 | ; AX = index to the segment | ||
| 1318 | ; | ||
| 1319 | ; exit: | ||
| 1320 | ; BX = pointer to the segment | ||
| 1321 | ; DX = pointer to the Current SIB | ||
| 1322 | ; | ||
| 1323 | |||
| 1324 | assume ds:Code,es:NOTHING | ||
| 1325 | |||
| 1326 | GetSegAdr: | ||
| 1327 | mov dx,(SIZE SEGst) | ||
| 1328 | mul dx ; multiply by size of SEG entry | ||
| 1329 | mov bx,[CurrSIB] ; pointer to SIB | ||
| 1330 | mov dx,bx ; save for exit | ||
| 1331 | mov bx,[bx].OffsetVal ; pointer to start of SEGs in SIB | ||
| 1332 | add bx,ax ; BX = pointer to SEG from start of SIB | ||
| 1333 | add bx,dx ; BX = absolute pointer to SEG to use | ||
| 1334 | ret | ||
| 1335 | |||
| 1336 | ifdef DEBUGFLG | ||
| 1337 | if NOT INBIOS | ||
| 1338 | INCLUDE BUGCODE.INC | ||
| 1339 | endif | ||
| 1340 | endif | ||
| 1341 | |||
| 1342 | |||
| 1343 | subttl $ConInit - Initialization Routine | ||
| 1344 | page | ||
| 1345 | |||
| 1346 | ;------------------------------------------------------------------------ | ||
| 1347 | ; Initialization Routine | ||
| 1348 | ; | ||
| 1349 | ;entry: | ||
| 1350 | ; DS:BX = pointer to Request packet | ||
| 1351 | ; ES:DI = Dos Functions entry point address | ||
| 1352 | ; | ||
| 1353 | |||
| 1354 | assume ds:NOTHING,es:NOTHING | ||
| 1355 | |||
| 1356 | $ConInit: | ||
| 1357 | IF NOT INBIOS | ||
| 1358 | push ds ; print greeting | ||
| 1359 | push cs | ||
| 1360 | pop ds | ||
| 1361 | mov dx,offset Intro | ||
| 1362 | MOV ah,9 | ||
| 1363 | int 21h | ||
| 1364 | pop ds | ||
| 1365 | mov word ptr ds:[bx].TRANS, offset $ConInit | ||
| 1366 | mov word ptr ds:[bx].TRANS+2,cs | ||
| 1367 | ENDIF | ||
| 1368 | mov cs:Word Ptr DosFunction,di ; Save pointer to service routines | ||
| 1369 | mov cs:Word Ptr DosFunction+2,es | ||
| 1370 | |||
| 1371 | mov ax,0 | ||
| 1372 | mov cx,1 | ||
| 1373 | mov dx,16 | ||
| 1374 | call [DosFunction] ; get DOS variable ScrnIoOk | ||
| 1375 | mov word ptr ScrnIoOk,ax | ||
| 1376 | mov word ptr ScrnIoOk+2,dx | ||
| 1377 | |||
| 1378 | ;* Initialize interrupt vectors. | ||
| 1379 | ;;BUGBUG - we should be using Get/Set_Interrupt_Vector calls | ||
| 1380 | |||
| 1381 | xor ax,ax ; initialize break interrupt handler | ||
| 1382 | mov es,ax ; points to page 0 | ||
| 1383 | mov ax,cs | ||
| 1384 | mov word ptr es:BRKADR,offset Break | ||
| 1385 | mov word ptr es:BRKADR+2,ax ; Vector for Break | ||
| 1386 | |||
| 1387 | MOV DI,9*4 ; INT 9 - Keyboard interrupt vector | ||
| 1388 | MOV CX,es:[DI] ; Save old addr to hook to | ||
| 1389 | MOV WORD PTR OldKeyInterrupt,CX | ||
| 1390 | MOV CX,es:2[DI] | ||
| 1391 | MOV WORD PTR (OldKeyInterrupt+2),CX | ||
| 1392 | MOV CX,OFFSET KeyboardInterrupt | ||
| 1393 | XCHG AX,CX | ||
| 1394 | STOSW | ||
| 1395 | XCHG AX,CX | ||
| 1396 | STOSW ; Set new keyboard interrupt | ||
| 1397 | |||
| 1398 | mov di,16h*4 ; INT 16 - keyboard input | ||
| 1399 | MOV CX,es:[DI] ; Save INT 16 addr to hook to | ||
| 1400 | MOV WORD PTR OldKbdHandler,CX | ||
| 1401 | MOV CX,es:2[DI] | ||
| 1402 | MOV WORD PTR (OldKbdHandler+2),CX | ||
| 1403 | MOV CX,OFFSET KeyboardHandler | ||
| 1404 | XCHG AX,CX | ||
| 1405 | STOSW | ||
| 1406 | XCHG AX,CX ; Set new keyboard Handler | ||
| 1407 | STOSW | ||
| 1408 | jmp StatusComplete | ||
| 1409 | |||
| 1410 | |||
| 1411 | IF INBIOS | ||
| 1412 | Code ends | ||
| 1413 | |||
| 1414 | BiosInit segment para public 'CODE' | ||
| 1415 | ENDIF | ||
| 1416 | |||
| 1417 | Intro db "--- Installing MTCON Device Driver V" | ||
| 1418 | db CVERS+"0",".",CREV/10+"0" | ||
| 1419 | db (CREV-CREV/10*10)+"0"," ---" | ||
| 1420 | db 13,10,"$" | ||
| 1421 | |||
| 1422 | BiosInit ends | ||
| 1423 | |||
| 1424 | END | ||
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 @@ | |||
| 1 | 29 May 1984 | ||
| 2 | |||
| 3 | The object files given here are sufficient to create the BIOS | ||
| 4 | for the IBM system. Some sources are given as examples for | ||
| 5 | OEM supplied device drivers. These sources do not necessarily | ||
| 6 | implement all the features described in the device driver | ||
| 7 | documentation. They have evolved in parallel with the | ||
| 8 | documentation, so some features described in the documentation | ||
| 9 | may not yet be present in the drivers. Below is a summary of | ||
| 10 | the 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 | |||