mirror of https://github.com/microsoft/MS-DOS.git
refactoring
This commit is contained in:
parent
80ab2fddfd
commit
025a58205f
|
@ -1,9 +0,0 @@
|
||||||
[MS-DOS 1.25 & 2.0 Source]
|
|
||||||
Copyright (c) Microsoft Corporation
|
|
||||||
All rights reserved.
|
|
||||||
MIT License
|
|
||||||
Permission is hereby granted, freeof charge, to any person obtaining a copy of this software and associateddocumentation files (the Software), to deal in the Software withoutrestriction, including without limitation the rights to use, copy, modify,merge, publish, distribute, sublicense, and/or sell copies of the Software, andto permit persons to whom the Software is furnished to do so, subject to thefollowing conditions:
|
|
||||||
|
|
||||||
The above copyright notice andthis permission notice shall be included in all copies or substantial portionsof the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED *AS IS*,WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TOTHE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE ANDNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLEFOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE ORTHE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
16
README.md
16
README.md
|
@ -1,16 +0,0 @@
|
||||||
<img width="150" height="150" style="float:left" alt="MS-DOS logo" src="https://github.com/Microsoft/MS-DOS/blob/master/msdos-logo.png">
|
|
||||||
|
|
||||||
# MS-DOS v1.25 and v2.0 Source Code
|
|
||||||
This repo contains the original source-code and compiled binaries for MS-DOS 1.25 and MS-DOS 2.0.
|
|
||||||
|
|
||||||
These are the same files [originally shared at the Computer History Museum on March 25th 2014]( http://www.computerhistory.org/atchm/microsoft-ms-dos-early-source-code/) and are being (re)published in this repo to make them easier to find, reference-to in external writing and works, and to allow exploration and experimentation for those interested in early PC Operating Systems.
|
|
||||||
|
|
||||||
# License
|
|
||||||
All files within this repo are released under the [MIT (OSI) License]( https://en.wikipedia.org/wiki/MIT_License) as per the [LICENSE file](https://githib.com/microsoft/msdos/license.txt) stored in the root of this repo.
|
|
||||||
|
|
||||||
# Contribute!
|
|
||||||
The source files in this repo are for historical reference and will be kept static, so please don’t send Pull Requests suggesting any modifications to the source files, but feel free to fork this repo and experiment 😊.
|
|
||||||
|
|
||||||
If, however, you’d like to submit additional non-source content or modifications to non-source files (e.g. this README), please submit via PR and we’ll review and consider.
|
|
||||||
|
|
||||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
BIN
msdos-logo.png
BIN
msdos-logo.png
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.0 KiB |
|
@ -1,23 +0,0 @@
|
||||||
From: Tim Paterson
|
|
||||||
To: Len Shustek
|
|
||||||
Date: Mon, 16 Dec 2013 10:34:17 -0800
|
|
||||||
Subject: RE: Source code to MS-DOS 1.0
|
|
||||||
|
|
||||||
|
|
||||||
I have found and attached the source code for MS-DOS 1.25 as shipped by Seattle Computer Products. Version 1.25 was the first general release to OEM customers other than IBM so was used by all the first clone manufacturers.
|
|
||||||
|
|
||||||
IBM's DOS 1.1 corresponds to MS-DOS 1.24. There is one minor difference between 1.24 and 1.25, as noted in the revision history at the top of MSDOS.ASM.
|
|
||||||
|
|
||||||
Of the file attached, only STDDOS.ASM/MSDOS.ASM (DOS main code) and COMMAND.ASM (command processor) would have been used by an OEM other than Seattle Computer. The other files:
|
|
||||||
|
|
||||||
IO.ASM - I/O system unique to SCP (equivalent to ibmbio.sys).
|
|
||||||
ASM.ASM & HEX2BIN.ASM - Old 8086 assembler developed by SCP (used to assemble older version of DOS).
|
|
||||||
TRANS.ASM - Z80 to 8086 assembly source code translator developed by SCP.
|
|
||||||
|
|
||||||
I also have a 6” stack of printouts of assembly listings for some of these and probably other related programs.
|
|
||||||
|
|
||||||
Tim Paterson
|
|
||||||
Paterson Technology
|
|
||||||
http://www.patersontech.com/
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4006
v1.25/source/ASM.ASM
4006
v1.25/source/ASM.ASM
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,214 +0,0 @@
|
||||||
; HEX2BIN version 1.02
|
|
||||||
; Converts Intel hex format files to straight binary
|
|
||||||
|
|
||||||
FCB: EQU 5CH
|
|
||||||
READ: EQU 20
|
|
||||||
SETDMA: EQU 26
|
|
||||||
OPEN: EQU 15
|
|
||||||
CLOSE: EQU 16
|
|
||||||
CREATE: EQU 22
|
|
||||||
DELETE: EQU 19
|
|
||||||
BLKWRT: EQU 40
|
|
||||||
GETSEG: EQU 38
|
|
||||||
BUFSIZ: EQU 1024
|
|
||||||
|
|
||||||
ORG 100H
|
|
||||||
PUT 100H
|
|
||||||
|
|
||||||
HEX2BIN:
|
|
||||||
MOV DI,FCB+9
|
|
||||||
CMP B,[DI]," "
|
|
||||||
JNZ HAVEXT
|
|
||||||
MOV SI,HEX
|
|
||||||
MOVB
|
|
||||||
MOVW
|
|
||||||
HAVEXT:
|
|
||||||
;Get load offset (default is -100H)
|
|
||||||
MOV CL,4 ;Needed for shifts
|
|
||||||
MOV [OFFSET],-100H
|
|
||||||
MOV SI,FCB+11H ;Scan second FCB for offset
|
|
||||||
LODB
|
|
||||||
CMP AL," " ;Check if offset present
|
|
||||||
JZ HAVOFF
|
|
||||||
MOV B,[SIGN],0 ;Assume positive sign for now
|
|
||||||
CMP AL,"+"
|
|
||||||
JZ GETOFF ;Get a positive offset
|
|
||||||
CMP AL,"-"
|
|
||||||
JNZ GETOFF1 ;If not + or -, then not signed
|
|
||||||
MOV B,[SIGN],1 ;Flag as negative offset
|
|
||||||
GETOFF:
|
|
||||||
LODB ;Eat sign
|
|
||||||
GETOFF1:
|
|
||||||
CALL HEXCHK ;Check for valid hex character
|
|
||||||
JC HAVOFF ;No offset if not valid
|
|
||||||
XOR BX,BX ;Intialize offset sum to 0
|
|
||||||
CONVOFF:
|
|
||||||
SHL BX,CL ;Multiply current sum by 16
|
|
||||||
OR BL,AL ;Add in current hex digit
|
|
||||||
LODB ;Get next digit
|
|
||||||
CALL HEXCHK ;And convert it to binary
|
|
||||||
JNC CONVOFF ;Loop until all hex digits read
|
|
||||||
TEST B,[SIGN],-1 ;Check if offset was to be negative
|
|
||||||
JZ SAVOFF
|
|
||||||
NEG BX
|
|
||||||
SAVOFF:
|
|
||||||
MOV [OFFSET],BX
|
|
||||||
HAVOFF:
|
|
||||||
MOV DX,STARTSEG
|
|
||||||
MOV AX,DS
|
|
||||||
ADD DX,AX ;Compute load segment
|
|
||||||
MOV AH,GETSEG
|
|
||||||
INT 33
|
|
||||||
MOV ES,DX
|
|
||||||
SEG ES
|
|
||||||
MOV CX,[6] ;Get size of segment
|
|
||||||
MOV [SEGSIZ],CX
|
|
||||||
XOR AX,AX
|
|
||||||
MOV DI,AX
|
|
||||||
MOV BP,AX
|
|
||||||
SHR CX
|
|
||||||
REP
|
|
||||||
STOW ;Fill entire segment with zeros
|
|
||||||
MOV AH,OPEN
|
|
||||||
MOV DX,FCB
|
|
||||||
INT 21H
|
|
||||||
OR AL,AL
|
|
||||||
JNZ NOFIL
|
|
||||||
MOV B,[FCB+32],0
|
|
||||||
MOV [FCB+14],BUFSIZ ;Set record size to buffer size
|
|
||||||
MOV DX,BUFFER
|
|
||||||
MOV AH,SETDMA
|
|
||||||
INT 33
|
|
||||||
MOV AH,READ
|
|
||||||
MOV DX,FCB ;All set up for sequential reads
|
|
||||||
MOV SI,BUFFER+BUFSIZ ;Flag input buffer as empty
|
|
||||||
READHEX:
|
|
||||||
CALL GETCH
|
|
||||||
CMP AL,":" ;Search for : to start line
|
|
||||||
JNZ READHEX
|
|
||||||
CALL GETBYT ;Get byte count
|
|
||||||
MOV CL,AL
|
|
||||||
MOV CH,0
|
|
||||||
JCXZ DONE
|
|
||||||
CALL GETBYT ;Get high byte of load address
|
|
||||||
MOV BH,AL
|
|
||||||
CALL GETBYT ;Get low byte of load address
|
|
||||||
MOV BL,AL
|
|
||||||
ADD BX,[OFFSET] ;Add in offset
|
|
||||||
MOV DI,BX
|
|
||||||
CALL GETBYT ;Throw away type byte
|
|
||||||
READLN:
|
|
||||||
CMP DI,[SEGSIZ]
|
|
||||||
JAE ADERR
|
|
||||||
CALL GETBYT ;Get data byte
|
|
||||||
STOB
|
|
||||||
CMP DI,BP ;Check if this is the largest address so far
|
|
||||||
JBE HAVBIG
|
|
||||||
MOV BP,DI ;Save new largest
|
|
||||||
HAVBIG:
|
|
||||||
LOOP READLN
|
|
||||||
JP READHEX
|
|
||||||
|
|
||||||
NOFIL:
|
|
||||||
MOV DX,NOFILE
|
|
||||||
QUIT:
|
|
||||||
MOV AH,9
|
|
||||||
INT 21H
|
|
||||||
INT 20H
|
|
||||||
|
|
||||||
ADERR:
|
|
||||||
MOV DX,ADDR
|
|
||||||
JMP SHOWERR
|
|
||||||
|
|
||||||
GETCH:
|
|
||||||
CMP SI,BUFFER+BUFSIZ
|
|
||||||
JNZ NOREAD
|
|
||||||
INT 21H
|
|
||||||
CMP AL,1
|
|
||||||
JZ ERROR
|
|
||||||
MOV SI,BUFFER
|
|
||||||
NOREAD:
|
|
||||||
LODB
|
|
||||||
CMP AL,1AH
|
|
||||||
JZ DONE
|
|
||||||
RET
|
|
||||||
|
|
||||||
GETBYT:
|
|
||||||
CALL HEXDIG
|
|
||||||
MOV BL,AL
|
|
||||||
CALL HEXDIG
|
|
||||||
SHL BL
|
|
||||||
SHL BL
|
|
||||||
SHL BL
|
|
||||||
SHL BL
|
|
||||||
OR AL,BL
|
|
||||||
RET
|
|
||||||
|
|
||||||
HEXCHK:
|
|
||||||
SUB AL,"0"
|
|
||||||
JC RET
|
|
||||||
CMP AL,10
|
|
||||||
JC CMCRET
|
|
||||||
SUB AL,"A"-"0"-10
|
|
||||||
JC RET
|
|
||||||
CMP AL,16
|
|
||||||
CMCRET:
|
|
||||||
CMC
|
|
||||||
RET
|
|
||||||
|
|
||||||
HEXDIG:
|
|
||||||
CALL GETCH
|
|
||||||
CALL HEXCHK
|
|
||||||
JNC RET
|
|
||||||
ERROR:
|
|
||||||
MOV DX,ERRMES
|
|
||||||
SHOWERR:
|
|
||||||
MOV AH,9
|
|
||||||
INT 21H
|
|
||||||
DONE:
|
|
||||||
MOV [FCB+9],4F00H+"C" ;"CO"
|
|
||||||
MOV B,[FCB+11],"M"
|
|
||||||
MOV DX,FCB
|
|
||||||
MOV AH,CREATE
|
|
||||||
INT 21H
|
|
||||||
OR AL,AL
|
|
||||||
JNZ NOROOM
|
|
||||||
XOR AX,AX
|
|
||||||
MOV [FCB+33],AX
|
|
||||||
MOV [FCB+35],AX ;Set RR field
|
|
||||||
INC AX
|
|
||||||
MOV [FCB+14],AX ;Set record size
|
|
||||||
XOR DX,DX
|
|
||||||
PUSH DS
|
|
||||||
PUSH ES
|
|
||||||
POP DS ;Get load segment
|
|
||||||
MOV AH,SETDMA
|
|
||||||
INT 21H
|
|
||||||
POP DS
|
|
||||||
MOV CX,BP
|
|
||||||
MOV AH,BLKWRT
|
|
||||||
MOV DX,FCB
|
|
||||||
INT 21H
|
|
||||||
MOV AH,CLOSE
|
|
||||||
INT 21H
|
|
||||||
EXIT:
|
|
||||||
INT 20H
|
|
||||||
|
|
||||||
NOROOM:
|
|
||||||
MOV DX,DIRFUL
|
|
||||||
JMP QUIT
|
|
||||||
|
|
||||||
HEX: DB "HEX"
|
|
||||||
ERRMES: DB "Error in HEX file--conversion aborted$"
|
|
||||||
NOFILE: DB "File not found$"
|
|
||||||
ADDR: DB "Address out of range--conversion aborted$"
|
|
||||||
DIRFUL: DB "Disk directory full$"
|
|
||||||
|
|
||||||
OFFSET: DS 2
|
|
||||||
SEGSIZ: DS 2
|
|
||||||
SIGN: DS 1
|
|
||||||
BUFFER: DS BUFSIZ
|
|
||||||
|
|
||||||
START:
|
|
||||||
STARTSEG EQU (START+15)/16
|
|
||||||
|
|
1934
v1.25/source/IO.ASM
1934
v1.25/source/IO.ASM
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,23 +0,0 @@
|
||||||
TITLE MS-DOS version 1.25 by Tim Paterson March 3, 1982
|
|
||||||
PAGE 60,132
|
|
||||||
; Use the following booleans to set the switches
|
|
||||||
FALSE EQU 0
|
|
||||||
TRUE EQU NOT FALSE
|
|
||||||
|
|
||||||
; Use the switches below to produce the standard Microsoft version of the IBM
|
|
||||||
; version of the operating system
|
|
||||||
MSVER EQU TRUE
|
|
||||||
IBM EQU FALSE
|
|
||||||
|
|
||||||
; Set this switch to cause DOS to move itself to the end of memory
|
|
||||||
HIGHMEM EQU FALSE
|
|
||||||
|
|
||||||
; Turn on switch below to allow testing disk code with DEBUG. It sets
|
|
||||||
; up a different stack for disk I/O (functions > 11) than that used for
|
|
||||||
; character I/O which effectively makes the DOS re-entrant.
|
|
||||||
|
|
||||||
DSKTEST EQU FALSE
|
|
||||||
|
|
||||||
INCLUDE MSDOS.ASM
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,802 +0,0 @@
|
||||||
MS-DOS 2.0 Device Drivers
|
|
||||||
|
|
||||||
INTRODUCTION
|
|
||||||
|
|
||||||
In the past, DOS-device driver (BIOS for those who are
|
|
||||||
familiar with CP/M) communication has been mediated with
|
|
||||||
registers and a fixed-address jump-table. This approach
|
|
||||||
has suffered heavily from the following two observations:
|
|
||||||
|
|
||||||
o The old jump-table ideas of the past are fixed in
|
|
||||||
scope and allow no extensibility.
|
|
||||||
|
|
||||||
o The past device driver interfaces have been written
|
|
||||||
without regard for the true power of the hardware.
|
|
||||||
When a multitasking system or interrupt driven
|
|
||||||
hardware is installed a new BIOS must be written
|
|
||||||
largely from scratch.
|
|
||||||
|
|
||||||
In MSDOS 2.0, the DOS-device driver interface has changed
|
|
||||||
from the old jump-table style to one in which the device
|
|
||||||
drivers are linked together in a list. This allows new
|
|
||||||
drivers for optional hardware to be installed (and even
|
|
||||||
written) in the field by other vendors or the user himself.
|
|
||||||
This flexibility is one of the major new features of MS-DOS
|
|
||||||
2.0.
|
|
||||||
|
|
||||||
Each driver in the chain defines two entry points; the
|
|
||||||
strategy routine and the interrupt routine. The 2.0 DOS
|
|
||||||
does not really make use of two entry points (it simply calls
|
|
||||||
strategy, then immediately calls interrupt). This dual entry
|
|
||||||
point scheme is designed to facilitate future multi-tasking
|
|
||||||
versions of MS-DOS. In multi-tasking environments I/O must
|
|
||||||
be asynchronous, to accomplish this the strategy routine
|
|
||||||
will be called to queue (internally) a request and return
|
|
||||||
quickly. It is then the responsibility of the interrupt
|
|
||||||
routine to perform the actual I/O at interrupt time by picking
|
|
||||||
requests off the internal queue (set up by the strategy
|
|
||||||
routine), and process them. When a request is complete,
|
|
||||||
it is flagged as "done" by the interrupt routine. The DOS
|
|
||||||
periodically scans the list of requests looking for ones
|
|
||||||
flagged as done, and "wakes up" the process waiting for the
|
|
||||||
completion of the request.
|
|
||||||
|
|
||||||
In order for requests to be queued as above it is no
|
|
||||||
longer sufficient to pass I/O information in registers, since
|
|
||||||
many requests may be pending at any one time. Therefore
|
|
||||||
the new device interface uses data "packets" to pass request
|
|
||||||
information. A device is called with a pointer to a packet,
|
|
||||||
this packet is linked into a global chain of all pending
|
|
||||||
I/O requests maintained by the DOS. The device then links
|
|
||||||
the packet into its own local chain of requests for this
|
|
||||||
particular device. The device interrupt routine picks
|
|
||||||
requests of the local chain for processing. The DOS scans
|
|
||||||
the global chain looking for completed requests. These
|
|
||||||
packets are composed of two pieces, a static piece which
|
|
||||||
has the same format for all requests (called the static
|
|
||||||
request header), which is followed by information specific
|
|
||||||
to the request. Thus packets have a variable size and format.
|
|
||||||
|
|
||||||
At this points it should be emphasized that MS-DOS 2.0
|
|
||||||
does not implement most of these features, as future versions
|
|
||||||
will. There is no global or local queue. Only one request
|
|
||||||
is pending at any one time, and the DOS waits for this current
|
|
||||||
request to be completed. For 2.0 it is sufficient for the
|
|
||||||
strategy routine to simply store the address of the packet
|
|
||||||
at a fixed location, and for the interrupt routine to then
|
|
||||||
process this packet by doing the request and returning.
|
|
||||||
Remember: the DOS just calls the strategy routine and then
|
|
||||||
immediately calls the interrupt routine, it is assumed that
|
|
||||||
the request is completed when the interrupt routine returns.
|
|
||||||
This additional functionality is defined at this time so
|
|
||||||
that people will be aware and thinking about the future.
|
|
||||||
|
|
||||||
|
|
||||||
FORMAT OF A DEVICE DRIVER
|
|
||||||
|
|
||||||
A device driver is simply a relocatable memory image
|
|
||||||
with all of the code in it to implement the device (like
|
|
||||||
a .COM file, but not ORGed at 100 Hex). In addition it has
|
|
||||||
a special header at the front of it which identifies it as
|
|
||||||
a device, defines the strategy and interrupt entry points,
|
|
||||||
and defines various attributes. It should also be noted
|
|
||||||
that there are two basic types of devices.
|
|
||||||
|
|
||||||
The first is character devices. These are devices which
|
|
||||||
are designed to do character I/O in a serial manner like
|
|
||||||
CON, AUX, and PRN. These devices are named (ie. CON, AUX,
|
|
||||||
CLOCK, etc.), and users may open channels (FCBs) to do I/O
|
|
||||||
to them.
|
|
||||||
|
|
||||||
The second class of devices is block devices. These
|
|
||||||
devices are the "disk drives" on the system, they can do
|
|
||||||
random I/O in pieces called blocks (usually the physical
|
|
||||||
sector size) and hence the name. These devices are not
|
|
||||||
"named" as the character devices are, and therefore cannot
|
|
||||||
be "opened" directly. Instead they are "mapped" via the
|
|
||||||
drive letters (A,B,C, etc.).
|
|
||||||
|
|
||||||
Block devices also have units. In other words a single
|
|
||||||
driver may be responsible for one or more disk drives. For
|
|
||||||
instance block device driver ALPHA (please note that we cannot
|
|
||||||
actually refer to block devices by a name!) may be
|
|
||||||
responsible for drives A,B,C and D, this simply means that
|
|
||||||
it has four units (0-3) defined and therefore takes up four
|
|
||||||
drive letters. Which units correspond to which drive letters
|
|
||||||
is determined by the position of the driver in the chain
|
|
||||||
of all drivers: if driver ALPHA is the first block driver
|
|
||||||
in the device chain, and it defines 4 units (0-3), then they
|
|
||||||
will be A,B,C and D. If BETA is the second block driver
|
|
||||||
and defines three units (0-2), then they will be E,F and
|
|
||||||
G and so on. MS-DOS 2.0 is not limited to 16 block device
|
|
||||||
units, as previous versions were. The theoretical limit
|
|
||||||
is 63 (2^6 - 1), but it should be noted that after 26 the
|
|
||||||
drive letters get a little strange (like ] \ and ^). NOTE:
|
|
||||||
Character devices cannot define multiple units (this because
|
|
||||||
they have only one name).
|
|
||||||
|
|
||||||
|
|
||||||
Here is what that special device header looks like:
|
|
||||||
|
|
||||||
+--------------------------------------+
|
|
||||||
| DWORD Pointer to next device |
|
|
||||||
| (Must be set to -1) |
|
|
||||||
+--------------------------------------+
|
|
||||||
| WORD Attributes |
|
|
||||||
| Bit 15 = 1 if char device 0 if blk |
|
|
||||||
| if bit 15 is 1 |
|
|
||||||
| Bit 0 = 1 if Current sti device |
|
|
||||||
| Bit 1 = 1 if Current sto output |
|
|
||||||
| Bit 2 = 1 if Current NUL device |
|
|
||||||
| Bit 3 = 1 if Current CLOCK dev |
|
|
||||||
| Bit 4 = 1 if SPECIAL |
|
|
||||||
| Bit 14 is the IOCTL bit (see below) |
|
|
||||||
| Bit 13 is the NON IBM FORMAT bit |
|
|
||||||
+--------------------------------------+
|
|
||||||
| WORD Pointer to Device strategy |
|
|
||||||
| entry point |
|
|
||||||
+--------------------------------------+
|
|
||||||
| WORD Pointer to Device interrupt |
|
|
||||||
| entry point |
|
|
||||||
+--------------------------------------+
|
|
||||||
| 8-BYTE character device name field |
|
|
||||||
| Character devices set a device name |
|
|
||||||
| For block devices the first byte is |
|
|
||||||
| The number of units |
|
|
||||||
+--------------------------------------+
|
|
||||||
|
|
||||||
Note that the device entry points are words. They must
|
|
||||||
be offsets from the same segment number used to point to
|
|
||||||
this table. Ie. if XXX.YYY points to the start of this
|
|
||||||
table, then XXX.strategy and XXX.interrupt are the entry
|
|
||||||
points.
|
|
||||||
|
|
||||||
A word about the Attribute field. This field is used
|
|
||||||
most importantly to tell the system whether this device is
|
|
||||||
a block or character device (bit 15). Most of other bits
|
|
||||||
are used to give selected character devices certain special
|
|
||||||
treatment (NOTE: these bits mean nothing on a block device).
|
|
||||||
Let's say a user has a new device driver which he wants to
|
|
||||||
be the standard input and output. Besides just installing
|
|
||||||
the driver he needs to tell SYSINIT (and the DOS) that he
|
|
||||||
wishes his new driver to override the current sti and sto
|
|
||||||
(the "CON" device). This is accomplished by setting the
|
|
||||||
attributes to the desired characteristics, so he would set
|
|
||||||
Bits 0 and 1 to 1 (note that they are separate!!). Similarly
|
|
||||||
a new CLOCK device could be installed by setting that
|
|
||||||
attribute, see the section at the end on the CLOCK device.
|
|
||||||
NOTE: that although there is a NUL device attribute, the
|
|
||||||
NUL device cannot be re-assigned. This attribute exists
|
|
||||||
for the DOS so that it can tell if the NUL device is being
|
|
||||||
used.
|
|
||||||
|
|
||||||
The NON IBM FORMAT bit applies only to block devices
|
|
||||||
and effects the operation of the get BPB device call (see
|
|
||||||
below).
|
|
||||||
|
|
||||||
The other bit of interest is the IOCTL bit which has
|
|
||||||
meaning on character or block devices. This bit tells the
|
|
||||||
DOS whether this device can handle control strings (via the
|
|
||||||
IOCTL system call).
|
|
||||||
|
|
||||||
If a driver cannot process control strings, it should
|
|
||||||
initially set this bit to 0. This tells the DOS to return
|
|
||||||
an error if an attempt is made (via IOCTL system call) to
|
|
||||||
send or receive control strings to this device. A device
|
|
||||||
which can process control strings should initialize it to
|
|
||||||
1. For drivers of this type, the DOS will make calls to
|
|
||||||
the IOCTL INPUT and OUTPUT device functions to send and
|
|
||||||
receive IOCTL strings (see IOCTL in the SYSTEM-CALLS
|
|
||||||
document).
|
|
||||||
|
|
||||||
The IOCTL functions allow data to be sent and received
|
|
||||||
by the device itself for its own use (to set baud rate, stop
|
|
||||||
bits, form length etc., etc.), instead of passing data over
|
|
||||||
the device channel as a normal read or write does. The
|
|
||||||
interpretation of the passed information is up to the device,
|
|
||||||
but it MUST NOT simply be treated as a normal I/O.
|
|
||||||
|
|
||||||
The SPECIAL bit applies only to character drivers and
|
|
||||||
more particularly to CON drivers. The new 2.0 interface
|
|
||||||
is a much more general and consistent interface than the
|
|
||||||
old 1.25 DOS interface. It allows for a number of additional
|
|
||||||
features of 2.0. It is also slower than 1.25 if old style
|
|
||||||
"single byte" system calls are made. To make most efficient
|
|
||||||
use of the interface all applications should block their
|
|
||||||
I/O as much as possible. This means make one XENIX style
|
|
||||||
system call to output X bytes rather than X system calls
|
|
||||||
to output one byte each. Also putting a device channel in
|
|
||||||
RAW mode (see IOCTL) provides a means of putting out
|
|
||||||
characters even FASTER than 1.25. To help alleviate the
|
|
||||||
CON output speed problem for older programs which use the
|
|
||||||
1 - 12 system calls to output large amounts of data the
|
|
||||||
SPECIAL bit has been implemented. If this bit is 1 it means
|
|
||||||
the device is the CON output device, and has implemented
|
|
||||||
an interrupt 29 Hex handler, where the 29 Hex handler is
|
|
||||||
defined as follows:
|
|
||||||
|
|
||||||
Interrupt 29h handlers
|
|
||||||
|
|
||||||
Input:
|
|
||||||
Character in AL
|
|
||||||
|
|
||||||
Function:
|
|
||||||
output the character in al to the user
|
|
||||||
screen.
|
|
||||||
Output:
|
|
||||||
None
|
|
||||||
Registers:
|
|
||||||
all registers except bx must be preserved.
|
|
||||||
No registers except for al have a known or
|
|
||||||
consistent value.
|
|
||||||
|
|
||||||
If a character device implements the SPECIAL bit, it
|
|
||||||
is the responsibility of the driver to install an address
|
|
||||||
at the correct location in the interrupt table for interrupt
|
|
||||||
29 Hex as part of its INIT code. IMPLICATION: There can
|
|
||||||
be only one device driver with the SPECIAL bit set in the
|
|
||||||
system. There is no check to insure this state.
|
|
||||||
|
|
||||||
WARNING: THIS FEATURE WILL NOT BE SUPPORTED IN FUTURE VERSIONS
|
|
||||||
OF THE OPERATING SYSTEM. IMPLICATION: Any application
|
|
||||||
(not device driver) which uses INT 29H directly will
|
|
||||||
not work on future versions, YOU HAVE BEEN WARNED.
|
|
||||||
|
|
||||||
In order to "make" a device driver that SYSINIT can
|
|
||||||
install, a memory image or .EXE (non-IBM only) format file
|
|
||||||
must be created with the above header at the start. The
|
|
||||||
link field should be initialized to -1 (SYSINIT fills it
|
|
||||||
in). The attribute field and entry points must be set
|
|
||||||
correctly, and if the device is a character device, the name
|
|
||||||
field must be filled in with the name (if a block device
|
|
||||||
SYSINIT will fill in the correct unit count). This name
|
|
||||||
can be any 8 character "legal" file name. In fact SYSINIT
|
|
||||||
always installs character devices at the start of the device
|
|
||||||
list, so if you want to install a new CON device all you
|
|
||||||
have to do is name it "CON". The new one is ahead of the
|
|
||||||
old one in the list and thus preempts the old one as the
|
|
||||||
search for devices stops on the first match. Be sure to
|
|
||||||
set the sti and sto bits on a new CON device!
|
|
||||||
|
|
||||||
NOTE: Since SYSINIT may install the driver anywhere, you
|
|
||||||
must be very careful about FAR memory references. You
|
|
||||||
should NOT expect that your driver will go in the same
|
|
||||||
place every time (The default BIOS drivers are exempted
|
|
||||||
from this of course).
|
|
||||||
|
|
||||||
|
|
||||||
INSTALLATION OF DEVICE DRIVERS
|
|
||||||
|
|
||||||
Unlike past versions MS-DOS 2.0 allows new device drivers
|
|
||||||
to be installed dynamically at boot time. This is
|
|
||||||
accomplished by the new SYSINIT module supplied by Microsoft,
|
|
||||||
which reads and processes the CONFIG.SYS file. This module
|
|
||||||
is linked together with the OEM default BIOS in a similar
|
|
||||||
manner to the way FORMAT is built.
|
|
||||||
|
|
||||||
One of the functions defined for each device is INIT.
|
|
||||||
This routine is called once when the device is installed,
|
|
||||||
and never again. The only thing returned by the init routine
|
|
||||||
is a location (DS:DX) which is a pointer to the first free
|
|
||||||
byte of memory after the device driver, (like a terminate
|
|
||||||
and stay resident). This pointer method can be used to "throw
|
|
||||||
away" initialization code that is only needed once, saving
|
|
||||||
on space.
|
|
||||||
|
|
||||||
Block devices are installed the same way and also return
|
|
||||||
a first free byte pointer as above, additional information
|
|
||||||
is also returned:
|
|
||||||
|
|
||||||
o The number of units is returned, this determines
|
|
||||||
logical device names. If the current maximum logical
|
|
||||||
device letter is F at the time of the install call,
|
|
||||||
and the init routine returns 4 as the number of units,
|
|
||||||
then they will have logical names G, H, I and J.
|
|
||||||
This mapping is determined by by the position of
|
|
||||||
the driver in the device list and the number of units
|
|
||||||
on the device (stored in the first byte of the device
|
|
||||||
name field).
|
|
||||||
|
|
||||||
o A pointer to a BPB (Bios Parameter Block) pointer
|
|
||||||
array is also returned. This will be similar to
|
|
||||||
the INIT table used in previous versions, but will
|
|
||||||
have more information in it. There is one table
|
|
||||||
for each unit defined. These blocks will be used
|
|
||||||
to build a DPB (Drive Parameter Block) for each of
|
|
||||||
the units. The pointer passed to the DOS from the
|
|
||||||
driver points to an array of n word pointers to BPBs
|
|
||||||
where n is the number of units defined. In this
|
|
||||||
way if all units are the same, all of the pointers
|
|
||||||
can point to the same BPB, saving space. NOTE: this
|
|
||||||
array must be protected (below the free pointer set
|
|
||||||
by the return) since the DPB will be built starting
|
|
||||||
at the byte pointed to by the free pointer. The
|
|
||||||
sector size defined must be less than or equal to
|
|
||||||
the maximum sector size defined at default BIOS init
|
|
||||||
time. If it isn't the install will fail. One new
|
|
||||||
piece of DPB info set from this table will be a "media
|
|
||||||
descriptor byte". This byte means nothing to the
|
|
||||||
DOS, but is passed to devices so that they know what
|
|
||||||
form of a DPB the DOS is currently using for a
|
|
||||||
particular Drive-Unit.
|
|
||||||
|
|
||||||
Block devices may take several approaches; they may be
|
|
||||||
dumb or smart. A dumb device would define a unit (and
|
|
||||||
therefore a DPB) for each possible media drive combination.
|
|
||||||
Unit 0 = drive 0 single side, unit 1 = drive 0 double side,
|
|
||||||
etc. For this approach media descriptor bytes would mean
|
|
||||||
nothing. A smart device would allow multiple media per unit,
|
|
||||||
in this case the BPB table returned at init must define space
|
|
||||||
large enough to accommodate the largest possible media
|
|
||||||
supported. Smart drivers will use the "media byte" to pass
|
|
||||||
around info about what media is currently in a unit. NOTE:
|
|
||||||
If the DPB is a "hybrid" made to get the right sizes, it
|
|
||||||
should give an invalid "media byte" back to the DOS.
|
|
||||||
|
|
||||||
The BOOT (default BIOS) drivers are installed pretty
|
|
||||||
much as above. The preset device list is scanned. If block
|
|
||||||
drivers are encountered they are installed as above (with
|
|
||||||
the exception that the break is not moved since the drivers
|
|
||||||
are already resident in the BIOS). Note that the logical
|
|
||||||
drive letters are assigned in list order, thus the driver
|
|
||||||
which is to have logical A must be the first unit of the
|
|
||||||
first block device in the list. The order of character
|
|
||||||
devices is also important. There must be at least 4 character
|
|
||||||
devices defined at boot which must be the first four devices
|
|
||||||
(of either type), the first will become standard input,
|
|
||||||
standard output, and standard error output. The second will
|
|
||||||
become standard auxiliary input and output, the third will
|
|
||||||
become standard list output, and the forth will become the
|
|
||||||
date/time (CLOCK) device. Thus the BIOS device list must
|
|
||||||
look like this:
|
|
||||||
|
|
||||||
->CON->AUX->PRN->CLOCK->any other block or character devices
|
|
||||||
|
|
||||||
THE DRIVER
|
|
||||||
|
|
||||||
A device driver will define the following functions:
|
|
||||||
|
|
||||||
Command Function
|
|
||||||
Code
|
|
||||||
|
|
||||||
0 INIT
|
|
||||||
1 MEDIA CHECK (Block only, NOP for character)
|
|
||||||
2 BUILD BPB " " " " "
|
|
||||||
3 IOCTL INPUT (Only called if device has IOCTL)
|
|
||||||
4 INPUT (read)
|
|
||||||
5 NON-DESTRUCTIVE INPUT NO WAIT (Char devs only)
|
|
||||||
6 INPUT STATUS " " "
|
|
||||||
7 INPUT FLUSH " " "
|
|
||||||
8 OUTPUT (write)
|
|
||||||
9 OUTPUT (Write) with verify
|
|
||||||
10 OUTPUT STATUS " " "
|
|
||||||
11 OUTPUT FLUSH " " "
|
|
||||||
12 IOCTL OUTPUT (Only called if device has IOCTL)
|
|
||||||
|
|
||||||
As mentioned before, the first entry point is the strategy
|
|
||||||
routine which is called with a pointer to a data block. This
|
|
||||||
call does not perform the request, all it does is queue it
|
|
||||||
(save the data block pointer). The second interrupt entry
|
|
||||||
point is called immediately after the strategy call. The
|
|
||||||
"interrupt" routine is called with no parameters, its primary
|
|
||||||
function is to perform the operation based on the queued
|
|
||||||
data block and set up any returns.
|
|
||||||
|
|
||||||
The "BUILD BPB" and "MEDIA CHECK" are the interesting
|
|
||||||
new ones, these are explained by examining the sequence of
|
|
||||||
events in the DOS which occurs when a drive access call (other
|
|
||||||
than read or write) is made:
|
|
||||||
|
|
||||||
I. Turn drive letter into DPB pointer by looking
|
|
||||||
for DPB with correct driver-unit number.
|
|
||||||
|
|
||||||
II. Call device driver and request media check for
|
|
||||||
Drive-Unit. DOS passes its current Media
|
|
||||||
descriptor byte (from DPB). Call returns:
|
|
||||||
|
|
||||||
Media Not Changed
|
|
||||||
Media Changed
|
|
||||||
Not Sure
|
|
||||||
Error
|
|
||||||
|
|
||||||
Error - If an error occurs the error code should
|
|
||||||
be set accordingly.
|
|
||||||
|
|
||||||
Media Not changed - Current DPB and media byte
|
|
||||||
are OK, done.
|
|
||||||
|
|
||||||
Media Changed - Current DPB and media are wrong,
|
|
||||||
invalidate any buffers for this unit, and
|
|
||||||
goto III.
|
|
||||||
|
|
||||||
Not Sure - If there are dirty buffers for this
|
|
||||||
unit, assume DPB and media byte are OK and
|
|
||||||
done. If nothing dirty, assume media changed,
|
|
||||||
invalidate any buffers for unit, and goto
|
|
||||||
III.
|
|
||||||
|
|
||||||
NOTE: If a hybrid DPB was built at init and
|
|
||||||
an invalid Media byte was set, the driver
|
|
||||||
should return media changed when this invalid
|
|
||||||
media byte is encountered.
|
|
||||||
|
|
||||||
III. Call device driver to build BPB with media byte
|
|
||||||
and buffer.
|
|
||||||
|
|
||||||
What the driver must do at step III is determine the
|
|
||||||
correct media that is currently in the unit, and return a
|
|
||||||
pointer to a BPB table (same as for the install call). This
|
|
||||||
table will be used as at init to build a correct DPB for
|
|
||||||
the unit If the determined media descriptor byte in the table
|
|
||||||
turns out to be the same as the one passed in, then the DOS
|
|
||||||
will not build a new table, but rather just use the old one.
|
|
||||||
Therefore in this case the driver doesn't have to correctly
|
|
||||||
fill in the other entries if desired.
|
|
||||||
|
|
||||||
The build BPB call also gets a pointer to a one sector
|
|
||||||
buffer. What this buffer contains is determined by the NON
|
|
||||||
IBM FORMAT bit in the attribute field. If the bit is zero
|
|
||||||
(device is IBM format compatible) then the buffer contains
|
|
||||||
the first sector of the first FAT, in particular the FAT
|
|
||||||
ID byte is the first byte of this buffer. NOTE: It must
|
|
||||||
be true that the BPB is the same, as far as location of the
|
|
||||||
FAT is concerned, for all possible media. This is because
|
|
||||||
this first FAT sector must be read BEFORE the actual BPB
|
|
||||||
is returned. If the NON IBM FORMAT bit is set then the
|
|
||||||
pointer points to one sector of scratch space which may be
|
|
||||||
used for anything.
|
|
||||||
|
|
||||||
CALL FORMAT
|
|
||||||
|
|
||||||
When the DOS calls a device driver to perform a finction,
|
|
||||||
it passes a structure (Drive Request Structure) in ES:BX
|
|
||||||
to perform operations and does a long call to the driver's
|
|
||||||
strategy entry point. This structure is a fixed length header
|
|
||||||
(Static Request Header) followed by data pertinent to the
|
|
||||||
operation being performed. NOTE: It is the drivers
|
|
||||||
responsibility to preserve machine state.
|
|
||||||
|
|
||||||
STATIC REQUEST HEADER ->
|
|
||||||
+-----------------------------+
|
|
||||||
| BYTE length of record |
|
|
||||||
| Length in bytes of this |
|
|
||||||
| Drive Request Structure |
|
|
||||||
+-----------------------------+
|
|
||||||
| BYTE unit code |
|
|
||||||
| The subunit the operation |
|
|
||||||
| is for (minor device) |
|
|
||||||
| (no meaning on character |
|
|
||||||
| devices) |
|
|
||||||
+-----------------------------+
|
|
||||||
| BYTE command code |
|
|
||||||
+-----------------------------+
|
|
||||||
| WORD Status |
|
|
||||||
+-----------------------------+
|
|
||||||
| 8 bytes reserved here for |
|
|
||||||
| two DWORD links. One will |
|
|
||||||
| be a link for the DOS queue |
|
|
||||||
| The other for the device |
|
|
||||||
| queue |
|
|
||||||
+-----------------------------+
|
|
||||||
|
|
||||||
STATUS WORD
|
|
||||||
|
|
||||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
|
||||||
+---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+
|
|
||||||
| E | | B | D | |
|
|
||||||
| R | RESERVED | U | O | ERROR CODE (bit 15 on)|
|
|
||||||
| R | | I | N | |
|
|
||||||
+---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+
|
|
||||||
|
|
||||||
The status word is zero on entry and is set by the driver
|
|
||||||
interrupt routine on return.
|
|
||||||
|
|
||||||
Bit 8 is the done bit, it means the operation is complete.
|
|
||||||
For the moment the Driver just sets it to one when it exits,
|
|
||||||
in the future this will be set by the interrupt routine to
|
|
||||||
tell the DOS the operation is complete.
|
|
||||||
|
|
||||||
Bit 15 is the error bit, if it is set then the low 8
|
|
||||||
bits indicate the error:
|
|
||||||
|
|
||||||
0 Write Protect violation
|
|
||||||
(NEW) 1 Unknown Unit
|
|
||||||
2 Drive not ready
|
|
||||||
(NEW) 3 Unknown command
|
|
||||||
4 CRC error
|
|
||||||
(NEW) 5 Bad Drive Request Structure length
|
|
||||||
6 Seek error
|
|
||||||
(NEW) 7 Unknown media
|
|
||||||
8 Sector not found
|
|
||||||
(NEW) 9 Printer out of paper
|
|
||||||
A Write Fault
|
|
||||||
(NEW) B Read Fault
|
|
||||||
C General Failure
|
|
||||||
|
|
||||||
Bit 9 is the busy bit which is set only by status calls (see
|
|
||||||
STATUS CALL below).
|
|
||||||
|
|
||||||
|
|
||||||
Here is the data block format for each function:
|
|
||||||
|
|
||||||
READ or WRITE - ES:BX (Including IOCTL) ->
|
|
||||||
+------------------------------------+
|
|
||||||
| 13-BYTE Static Request Header |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE Media descriptor from DPB |
|
|
||||||
+------------------------------------+
|
|
||||||
| DWORD transfer address |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD byte/sector Count |
|
|
||||||
---+------------------------------------+---
|
|
||||||
| WORD starting sector number |
|
|
||||||
| (ignored on Char Devs) |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
In addition to setting the status word, the driver must
|
|
||||||
set the Sector count to the actual number of sectors (or
|
|
||||||
bytes) transferred. NOTE: No error check is performed on
|
|
||||||
an IOCTL I/O call, driver MUST correctly set the return sector
|
|
||||||
(byte) count to the actual number of bytes transferred,
|
|
||||||
however.
|
|
||||||
|
|
||||||
NOTE: THE FOLLOWING APPLIES TO BLOCK DEVICE DRIVERS.
|
|
||||||
|
|
||||||
Under certain circumstances the BIOS may be asked to
|
|
||||||
do a write operation of 64K bytes which seems to be a "wrap
|
|
||||||
around" of the transfer address in the BIOS I/O packet. This
|
|
||||||
arises due to an optimization added to the write code in
|
|
||||||
MS-DOS. It will only manifest on user WRITEs which are within
|
|
||||||
a sector size of 64K bytes on files which are "growing" past
|
|
||||||
the current EOF. IT IS ALLOWABLE FOR THE BIOS TO IGNORE
|
|
||||||
THE BALANCE OF THE WRITE WHICH "WRAPS AROUND" IF IT SO
|
|
||||||
CHOOSES. For instance a WRITE of 10000H bytes worth of
|
|
||||||
sectors with a transfer address of XXX:1 could ignore the
|
|
||||||
last two bytes (remember that a user program can never request
|
|
||||||
an I/O of more than FFFFH bytes and cannot wrap around (even
|
|
||||||
to 0) in his transfer segment, so in this case the last two
|
|
||||||
bytes can be ignored).
|
|
||||||
|
|
||||||
|
|
||||||
NON DESRUCTIVE READ NO WAIT - ES:BX ->
|
|
||||||
+------------------------------------+
|
|
||||||
| 13-BYTE Static Request Header |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE read from device |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
This call is analogous to the console input status call
|
|
||||||
on MS-DOS 1.25. If the character device returns Busy bit
|
|
||||||
= 0 (characters in buffer), then the next character that
|
|
||||||
would be read is returned. This character is NOT removed
|
|
||||||
from the input buffer (hence the term Non Destructive Read).
|
|
||||||
In essence this call allows the DOS to look ahead one input
|
|
||||||
character.
|
|
||||||
|
|
||||||
|
|
||||||
MEDIA CHECK - ES:BX ->
|
|
||||||
+------------------------------------+
|
|
||||||
| 13-BYTE Static Request Header |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE Media Descriptor from DPB |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE returned |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
In addition to setting status word, driver must set the
|
|
||||||
return byte.
|
|
||||||
|
|
||||||
Return Byte :
|
|
||||||
-1 Media has been changed
|
|
||||||
0 Don't know if media has been changed
|
|
||||||
1 Media has not been changed
|
|
||||||
|
|
||||||
If the driver can return -1 or 1 (by having a door-lock
|
|
||||||
or other interlock mechanism) the performance of MSDOS 2.0
|
|
||||||
is enhanced as the DOS need not reread the FAT for each
|
|
||||||
directory access.
|
|
||||||
|
|
||||||
|
|
||||||
BUILD BPB - ES:BX ->
|
|
||||||
+------------------------------------+
|
|
||||||
| 13-BYTE Static Request Header |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE Media Descriptor from DPB |
|
|
||||||
+------------------------------------+
|
|
||||||
| DWORD Transfer Address |
|
|
||||||
| (points to one sectors worth of |
|
|
||||||
| scratch space or first sector |
|
|
||||||
| of FAT depending on the value |
|
|
||||||
| of the NON IBM FORMAT bit) |
|
|
||||||
+------------------------------------+
|
|
||||||
| DWORD Pointer to BPB |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
If the NON IBM FORMAT bit of the device is set, then
|
|
||||||
the DWORD Transfer Address points to a one sector buffer
|
|
||||||
which can be used for any purpose. If the NON IBM FORMAT
|
|
||||||
bit is 0, then this buffer contains the first sector of the
|
|
||||||
FAT; in this case the driver must not alter this buffer (this
|
|
||||||
mode is useful if all that is desired is to read the FAT
|
|
||||||
ID byte).
|
|
||||||
|
|
||||||
If IBM compatible format is used (NON IBM FORMAT BIT
|
|
||||||
= 0), then it must be true that the first sector of the first
|
|
||||||
FAT is located at the same sector on all possible media.
|
|
||||||
This is because the FAT sector will be read BEFORE the media
|
|
||||||
is actually determined.
|
|
||||||
|
|
||||||
In addition to setting status word, driver must set the
|
|
||||||
Pointer to the BPB on return.
|
|
||||||
|
|
||||||
|
|
||||||
In order to allow for many different OEMs to read each
|
|
||||||
other's disks, the following standard is suggested: The
|
|
||||||
information relating to the BPB for a particular piece of
|
|
||||||
media is kept in the boot sector for the media. In
|
|
||||||
particular, the format of the boot sector is:
|
|
||||||
|
|
||||||
+------------------------------------+
|
|
||||||
| 3 BYTE near JUMP to boot code |
|
|
||||||
+------------------------------------+
|
|
||||||
| 8 BYTES OEM name and version |
|
|
||||||
---+------------------------------------+---
|
|
||||||
B | WORD bytes per sector |
|
|
||||||
P +------------------------------------+
|
|
||||||
B | BYTE sectors per allocation unit |
|
|
||||||
+------------------------------------+
|
|
||||||
| | WORD reserved sectors |
|
|
||||||
V +------------------------------------+
|
|
||||||
| BYTE number of FATs |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD number of root dir entries |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD number of sectors in logical |
|
|
||||||
^ | image |
|
|
||||||
| +------------------------------------+
|
|
||||||
B | BYTE media descriptor |
|
|
||||||
P +------------------------------------+
|
|
||||||
B | WORD number of FAT sectors |
|
|
||||||
---+------------------------------------+---
|
|
||||||
| WORD sectors per track |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD number of heads |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD number of hidden sectors |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
The three words at the end are optional, the DOS doesn't
|
|
||||||
care about them (since they are not part of the BPB). They
|
|
||||||
are intended to help the BIOS understand the media. Sectors
|
|
||||||
per track may be redundant (could be figured out from total
|
|
||||||
size of the disk). Number of heads is useful for supporting
|
|
||||||
different multi-head drives which have the same storage
|
|
||||||
capacity, but a different number of surfaces. Number of
|
|
||||||
hidden sectors is useful for supporting drive partitioning
|
|
||||||
schemes.
|
|
||||||
|
|
||||||
|
|
||||||
Currently, the media descriptor byte has been defined
|
|
||||||
for a small range of media:
|
|
||||||
|
|
||||||
5 1/4" diskettes:
|
|
||||||
|
|
||||||
Flag bits:
|
|
||||||
01h - on -> 2 double sided
|
|
||||||
|
|
||||||
All other bits must be on.
|
|
||||||
|
|
||||||
8" disks:
|
|
||||||
FEh - IBM 3740 format, singled-sided, single-density,
|
|
||||||
128 bytes per sector, soft sectored, 4 sectors
|
|
||||||
per allocation unit, 1 reserved sector, 2 FATs,
|
|
||||||
68 directory entries, 77*26 sectors
|
|
||||||
|
|
||||||
FDh - 8" IBM 3740 format, singled-sided,
|
|
||||||
single-density, 128 bytes per sector, soft
|
|
||||||
sectored, 4 sectors per allocation unit, 4
|
|
||||||
reserved sectors, 2 FATs, 68 directory entries,
|
|
||||||
77*26 sectors
|
|
||||||
|
|
||||||
FEh - 8" Double-sided, double-density, 1024 bytes
|
|
||||||
per sector, soft sectored, 1 sector per allocation
|
|
||||||
unit, 1 reserved sector, 2 FATs, 192 directory
|
|
||||||
entries, 77*8*2 sectors
|
|
||||||
|
|
||||||
|
|
||||||
STATUS Calls - ES:BX ->
|
|
||||||
+------------------------------------+
|
|
||||||
| 13-BYTE Static Request Header |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
All driver must do is set status word accordingly and
|
|
||||||
set the busy bit as follows:
|
|
||||||
|
|
||||||
o For output on character devices: If it is 1 on
|
|
||||||
return, a write request (if made) would wait for
|
|
||||||
completion of a current request. If it is 0, there
|
|
||||||
is no current request and a write request (if made)
|
|
||||||
would start immediately.
|
|
||||||
|
|
||||||
o For input on character devices with a buffer a return
|
|
||||||
of 1 means, a read request (if made) would go to
|
|
||||||
the physical device. If it is 0 on return, then
|
|
||||||
there are characters in the devices buffer and a
|
|
||||||
read would return quickly, it also indicates that
|
|
||||||
the user has typed something. The DOS assumes all
|
|
||||||
character devices have an input type ahead buffer.
|
|
||||||
Devices which don't have them should always return
|
|
||||||
busy = 0 so that the DOS won't hang waiting for
|
|
||||||
something to get into a buffer which doesn't exist.
|
|
||||||
|
|
||||||
|
|
||||||
FLUSH Calls - ES:BX ->
|
|
||||||
+------------------------------------+
|
|
||||||
| 13-BYTE Static Request Header |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
This call tells the driver to flush (terminate) all
|
|
||||||
pending requests that it has knowledge of. Its primary use
|
|
||||||
is to flush the input queue on character devices.
|
|
||||||
|
|
||||||
|
|
||||||
INIT - ES:BX ->
|
|
||||||
+------------------------------------+
|
|
||||||
| 13-BYTE Static Request Header |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE # of units |
|
|
||||||
+------------------------------------+
|
|
||||||
| DWORD Break Address |
|
|
||||||
---+------------------------------------+---
|
|
||||||
| DWORD Pointer to BPB array |
|
|
||||||
| (not set by Character devices) |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
The number of units, break address, and BPB pointer are
|
|
||||||
set by the driver.
|
|
||||||
|
|
||||||
|
|
||||||
FORMAT OF BPB (Bios Parameter Block) -
|
|
||||||
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD Sector size in Bytes |
|
|
||||||
| Must be at least 32 |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE Sectors/Allocation unit |
|
|
||||||
| Must be a power of 2 |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD Number of reserved sectors |
|
|
||||||
| May be zero |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE Number of FATS |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD Number of directory entries |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD Total number of sectors |
|
|
||||||
+------------------------------------+
|
|
||||||
| BYTE Media descriptor |
|
|
||||||
+------------------------------------+
|
|
||||||
| WORD Number of sectors occupied by |
|
|
||||||
| FAT |
|
|
||||||
+------------------------------------+
|
|
||||||
|
|
||||||
|
|
||||||
THE CLOCK DEVICE
|
|
||||||
|
|
||||||
One of the most popular add on boards seems to be "Real
|
|
||||||
Time CLOCK Boards". To allow these boards to be integrated
|
|
||||||
into the system for TIME and DATE, there is a special device
|
|
||||||
(determined by the attribute word) which is the CLOCK device.
|
|
||||||
In all respects this device defines and performs functions
|
|
||||||
like any other character device (most functions will be "set
|
|
||||||
done bit, reset error bit, return). When a read or write
|
|
||||||
to this device occurs, exactly 6 bytes are transferred. This
|
|
||||||
I/O can be thought of as transferring 3 words which correspond
|
|
||||||
exactly to the values of AX, CX and DX which were used in
|
|
||||||
the old 1.25 DOS date and time routines. Thus the first
|
|
||||||
two bytes are a word which is the count of days since 1-1-80.
|
|
||||||
The third byte is minutes, the fourth hours, the fifth
|
|
||||||
hundredths of seconds, and the sixth seconds. Reading the
|
|
||||||
CLOCK device gets the date and time, writing to it sets the
|
|
||||||
date and time.
|
|
||||||
|