MICROSOFT(R) MS(tm)-DOS Adaptation Guide Last Updated on JULY 24, 1987 in conjunction with the MS-DOS 3.30 FINAL RELEASE Microsoft Corporation Information in this document is subject to change without notice and does not represent a commitment on the part of Microsoft Corporation. The software described in this document is furnished under a license agreement or non-disclosure agreement. The software may be used or copied only in accordance with the terms of that agreement. It is against the law to copy the MS-DOS Disk Operating System on magnetic tape, disk, or any other medium for any purpose other than the purchaser's personal use. Copyright (C) Microsoft Corporation, 1982, 1983, 1984, 1985, 1986 INTEL is a registered trademark of Intel Corporation. IBM is a registered trademark of International Business Machines Corporation. Microsoft, the Microsoft logo, and MS-DOS are registered trademarks of Microsoft Corporation. XENIX is a trademark of Microsoft Corporation. TABLE OF CONTENTS CHAPTER 1 MS-DOS INSTALLATION KIT 1.1 README.DOC File 1-1 CHAPTER 2 MS-DOS DEVELOPMENT TOOLS CHAPTER 3 INSTALLING MS-DOS CHAPTER 4 DISK STRUCTURE AND BOOTSTRAP LOADING CHAPTER 5 RESIDENT DEVICE DRIVERS CHAPTER 6 SYSINIT AND MS-DOS INITIALIZATION CHAPTER 7 WRITING THE FORMAT MODULE CHAPTER 8 TROUBLE SHOOTING APPENDIX A CUSTOMIZATION OF MS-DOS AND INTERNATIONALIZATION A.1 Customizing MS-DOS A-1 A.2 ECS Considerations -- MS-DOS 2.25 A-2 A.3 Input A-3 A.4 Output A-3 APPENDIX B HOW TO UPGRADE A 2.X BIOS TO 3.X APPENDIX C HOW TO UPGRADE A 3.1 BIOS TO 3.2 APPENDIX D DEVICE DRIVERS - CHAPTER 2 MS-DOS 3.20 PROGRAMMER'S REFERENCE APPENDIX E MS-DOS 2.25 DEVICE DRIVER EXTENSIONS APPENDIX F MS-DOS 2.25 APPLICATION LEVEL INTERFACE EXTENSION APPENDIX G SPECIAL DOC APPENDIX H PROGRAMMING RECOMMENDATIONS - CHAPTER 7 MS-DOS 3.20 PROGRAMMER'S REFERENCE GLOSSARY OF MS-DOS TERMS CONTENTS CHAPTER 1 MS-DOS INSTALLATION KIT 1.1 README.DOC File 1-1 1.2 Contents 1-1 1.3 Common Questions and Answers 1-2 1.4 MS-DOS Hardware Requirements 1-3 1.5 MS-DOS Overview 1-5 CHAPTER 1 MS-DOS INSTALLATION KIT 1.1 README.DOC FILE Check the README.DOC file on DISTRIBUTION DISKETTES for version specific information and any addenda to this document. 1.2 CONTENTS The MS-DOS 3.21 Installation Kit is provided on 5-1/4" high capacity 1.2 Megabyte disks. It consists of the MS-DOS DISTRIBUTION DISKETTES that include files formerly found version. Included with the kit is a Sample MS-DOS 2.XX/3.XX Implementation. The sample implementation runs on all members of the IBM PC family and is intended to be functionally equivalent to the IBM implementation. The purpose of this sample is to assist Microsoft OEMs with their MS-DOS installations, but can also be used directly as part of the OEMs product. IO.SYS, the BIOS, has been intended to be self documenting and Microsoft will support services for it as it run on IBM PCs. Included in the kit is a copy of the current Microsoft(R) Macro Assembler featuring SYMDEB, the symbolic debugger. The full MASM retail package is no longer provided. The installation kit also includes four manuals: MS-DOS User's Guide. This is an introduction to ______ ______ _____ MS-DOS, including how to start the system and use applications. MS-DOS User's Reference Manual. This manual ______ ______ _________ ______ explains hierarchical directories, the MS-DOS file structure, and MS-DOS commands and utilities. This manual is new in 3.XX. MS-DOS Programmer's Reference Manual. This manual ______ ____________ _________ ______ includes a summary of all published system calls and MS-DOS structures. MS-DOS Adaptation Guide. This manual describes how ______ __________ _____ to implement MS-DOS on OEM machines. This guide is available on diskette only and is the text you are now reading. MS-DOS INSTALLATION KIT Page 1-2 1.3 COMMON QUESTIONS AND ANSWERS Q. What kind of development machine do you recommend? A. Microsoft recommends that an MS-DOS machine be used as a development tool in preparing software for your target machine. Using an MS-DOS machine avoids problems with incompatible assemblers and object module formats. You may want to read standard MS-DOS disk formats. Using the development machine to build a system disk for the target machine simplifies the implementation process. Q. Are sources available? A. Sources for MS-DOS are not available (except for the sample BIOS implementation). Q. What language is MS-DOS written in? A. The source code for MS-DOS and most utilities is written in 8086 assembler code. It is compatible with the macro facility found in Microsoft Macro Assembler for the MS-DOS operating system. The format of the object modules provided is a subset of the INTEL(R) format, and may not be compatible with non-Microsoft linkers. Q. What does an MS-DOS implementor need to know? A. To install MS-DOS, you will need to be familiar with systems programming in 8086 assembler language. This means you should have experience in writing device drivers for disk drives, keyboards, printers, and other peripherals. Q. How long does it take to install MS-DOS? A. This depends on whether the low-level I/O routines are already written. The record time for getting MS-DOS up and running on a new machine is one weekend. In this case, all of the low-level routines were in ROM. Typically, a complete customer-ready MS-DOS implementation takes two or more months. MS-DOS INSTALLATION KIT Page 1-3 Q. Are there any consultants who do MS-DOS implementations? A. Microsoft can supply a list of consultants who have done MS-DOS implementations. Microsoft cannot make any recommendations regarding the competence of these consultants. Q. Do you recommend that we have an In Circuit Emulator (ICE) for our machine? A. Yes. Since there are no MS-DOS debugging tools that can be used to debug the boot sequence, an ICE is very helpful. 1.4 MS-DOS HARDWARE REQUIREMENTS To be compatible with the MS-DOS operating system, a machine must conform to certain hardware characteristics. These characteristics are as follows: o The processor must be INTEL 8086 compatible. o The Interrupt vector locations 20H through 3FH must be reserved for MS-DOS. o Four character device drivers and one block device driver are required. They must recognize the MS-DOS device driver call format. o An ANSI terminal driver must be implemented. (MS-DOS sends an ANSI escape sequence to clear the console.) o A logical disk, as described in this document, must be available to MS-DOS. A disk format table, as described in this document, should be present in the first logical sector of each disk. Logical sectors must be a multiple of 64 bytes in size. o Random Access Memory (RAM) should be contiguous from the point where MS-DOS is located through top of memory. o MS-DOS requires a minimum of 128K of RAM (depending on IO.SYS size). Microsoft recommends a minimum configuration of 128K non-video RAM and 192K for future products. The sample BIOS that is provided has been designed to only run on a machine with the exact architecture of IBM PC family. If MS-DOS can run on the OEMs hardware using the sample BIOS, then the hardware is compatible with the IBM PC family architecture. MS-DOS INSTALLATION KIT Page 1-4 In addition to these minimum requirements, the following hardware features are recommended for optimum performance as well as compatibility with new Microsoft products. Features recommended for performance on 2.0 and higher systems are starred. o *An interrupt-driven keyboard with a type-ahead buffer (Interrupt-driven I/O for all devices). o *Direct memory access. o *Non-interlaced disks. o *Disk door locks or a detection mechanism to check if disks have been changed. o Support of standard MS-DOS disk formats. o User-addressable bit-mapped video display with minimum resolution of 640 by 200 pixels. o Programmable interval timer. o Mouse support. o RS-232 and printer interfaces. o Minimum 192K RAM memory. o A Scroll Lock/Break key that puts a Control-S and Control-C at the beginning of the keyboard type-ahead buffer when pressed. MS-DOS INSTALLATION KIT Page 1-5 1.5 MS-DOS OVERVIEW An MS-DOS implementation requires seven components: 1. The resident device drivers (the IO.SYS file), a collection of hardware-specific device drivers that must be written by the OEM. The resident device drivers are called by MS-DOS to handle I/O requests. These device drivers may be partly ROM resident or may be completely RAM resident. 2. The SYSINIT Module(s), (SYSINIT1.OBJ and SYSINIT2.OBJ in 3.xx and only SYSINIT.OBJ in 2.xx) and SYSIMES.OBJ, Microsoft-supplied modules which are linked to the resident device drivers and initialize the system. The file that contains these device drivers is named IO.SYS (on the IBM(R) PC, this file is named IBMBIO.COM). 3. MSDOS.SYS, the hardware-independent disk operating system supplied by Microsoft. (On the IBM PC, this file is named IBMDOS.COM.) 4. COMMAND.COM, the command interpreter program that reads and interprets keyboard input, executes "built-in" commands like DIR, and initiates external programs. 5. Bootstrap loader, the OEM-supplied module that loads the IO.SYS and MSDOS.SYS files into memory. MSDOS.SYS may optionally be loaded by IO.SYS. A sample bootstrap loader has been provided with the OEM kit. This sample bootstrap loader is compatible with the IBM PC family. 6. A system ROM which may optionally perform diagnostics on power-up or reset. The system ROM loads the boot sector into RAM and transfers control to it. 7. MS-DOS utilities, including FORMAT, for which Microsoft modules are provided and a hardware-specific section must be written by the OEM. NOTE: Refer to the MS-DOS 3.3 specific portions for use of the hardware independent FORMAT utility. MS-DOS INSTALLATION KIT CONTENTS CHAPTER 2 MS-DOS DEVELOPMENT TOOLS EDLIN Text Editor 2-1 Microsoft Macro Assembler 2-1 Microsoft Linker (MS-LINK) 2-2 MS-DEBUG 2-2 EXE2BIN 2-2 FORMAT 2-2 CHAPTER 2 MS-DOS DEVELOPMENT TOOLS An assembler, text editor, linker, and other utilities are required for completing an MS-DOS implementation. We assume that your development machine has the following standard utilities: EDLIN Text Editor The EDLIN text editor provided with MS-DOS for your development machine may be used to prepare assembler source files. The version of EDLIN on MS-DOS 2.x and 3.x release disks is for versions 2.x and 3.x only, and will not run under MS-DOS 1.x. A third party full screen text editor (not a word processor) may be more efficient for manipulating source files. Microsoft Macro Assembler A complimentary copy of the current Microsoft Macro Assembler is provided with the MS-DOS installation kit. The assembler is not actually a part of MS-DOS; it must be licensed separately if you wish to ship it to your customers. The Cross-Reference Utility (MS-CREF), included with Microsoft Macro Assembler, can be used to make cross-reference listings of assembler programs. The Microsoft Macro Assembler package will only run under MS-DOS 2.XX and later operating systems. The output of the assembler is a relocatable object module (.OBJ file type) which conforms to a subset of the INTEL MCS 86 object module format description. Refer to the MS-DOS Programmer's Reference Manual for ______ ____________ _________ ______ information on the INTEL MCS 86 object module format description. MS-DOS DEVELOPMENT TOOLS Page 2-2 Microsoft Linker (MS-LINK) Your MS-DOS development machine should include a linker named LINK.EXE. Use LINK.EXE for linking object modules (.OBJ files) produced by the Microsoft Macro Assembler. The output of the Linker is a file with an .EXE format. This is an executable program requiring a special loader that is part of MS-DOS. Refer to the MS-DOS Programmer's Reference Manual for details on ______ ____________ _________ ______ .EXE formats. SYMDEB SYMDEB.EXE is the MS-DOS symbolic debugger. The debugger can do absolute disk reads and writes. You may use this facility to write your bootstrap loader program into the boot sector. Note that since MS-DOS is not reentrant, this debugger may not be used to set break points within the DOS or device drivers. EXE2BIN The EXE2BIN.EXE utility supplied with your MS-DOS development machine must be used for converting output from the Linker (.EXE files) to a pure binary (core image) format not requiring a special loader. Note that only .COM files may execute out of ROM. FORMAT The FORMAT program (FORMAT.EXE) supplied with your MS-DOS development machine may be used to format a boot disk for the target machine, assuming both machines have compatible media. EXEFIX EXEFIX is a special purpose utility used for building SORT. It sets the maximum memory allocation. MS-DOS DEVELOPMENT TOOLS CONTENTS CHAPTER 3 INSTALLING MS-DOS CHAPTER 3 INSTALLING MS-DOS If you are using an MS-DOS machine for development and your target machine will read MS-DOS standard disk formats, follow these steps to implement MS-DOS. NOTE: The steps involved in developing IO.SYS are not necessary if the sample BIOS provided with the OEM kit is used. This sample can also be used for technical reference. 1. Using a text editor on your development machine, write the 8086 assembler source code for the resident device drivers. The resident device drivers are the hardware-specific routines that will be accessed by MS-DOS to perform I/O. There must be a minimum of five device drivers: four ____ character drivers and one block device driver (the disk drive on most systems). In addition to the device drivers, you may want to include some code for hardware initialization. The source file should be named IO.ASM and must not contain a STACK segment. For more information, see: MS-DOS Programmer's Reference Manual ______ ____________ _________ ______ IO.ASM on the distribution disk The resident device driver section of this manual 2. Use MASM.EXE, the macro assembler provided with your MS-DOS installation kit to assemble your device driver code. MASM will create a file called IO.OBJ, which is in a special object module format (a subset of INTEL's object module format). For more information, see: Microsoft Macro Assembler Manual (Macro Assembler _________ _____ _________ ______ section) 3. Use LINK.EXE, the Microsoft Linker, to link your IO.OBJ module to appropriate SYSINIT.OBJ module(s)and the appropriate SYSIMES.OBJ module. The modules must be linked in this order: 2.xx IO.OBJ+SYSINIT.OBJ+SYSIMES.OBJ 3.XX IO.OBJ+SYSINIT1.OBJ+SYSINIT2.OBJ+SYSIMES.OBJ The output file should be named IO.EXE. You INSTALLING MS-DOS Page 3-2 may get the message "Warning, no STACK segment" while linking the module. This is a warning message and is normal with some versions of the linker. For more information, see: Microsoft Macro Assembler Manual (Chapter 3 LINK: _________ _____ _________ ______ A Linker) 4. The file created in step 3 is an .EXE file which is in a special format recognized by the .EXE loader. Since the .EXE loader is not available at boot time, the IO.EXE file must be converted to a pure binary core image file. This is done with the EXE2BIN utility provided with the MS-DOS release on your development machine. The EXE2BIN utility must know exactly where the code will reside in memory to resolve any FAR references. You will be prompted for the base address, the absolute segment address where the code will begin. The resultant file must be named IO.SYS. EXE2BIN will change the name when you type the following command line: EXE2BIN IO.EXE IO.SYS ------------------------------------------------------------ | | | Note | | | | It is the responsibility of the bootstrap loader to | | locate IO.SYS at the location you specified as the base | | address. The location itself is arbitrary, since one | | of the parameters that the resident device driver code | | passes to SYSINIT is the location of the first device | | driver. | | | |__________________________________________________________| For more information, see: MS-DOS User's Reference Manual (Chapter 3) ______ ______ _________ ______ 5. Customize the function key table in DOSMES.ASM. 6. Use MSDOSBLD.BAT on the distribution disk to assemble appropriate object modules and link them with those already provided to form MSDOS.SYS. 7. Write a bootstrap loader program using the text editor. This step is not necessary if the sample bootstrap loader included in the OEM kit is used. The sample bootstrap loader can also be used for technical reference. Name this file BOOT.ASM. We assume that you have a system ROM which will load the first sector of the system disk into memory when you turn on or reset the compter. Ideally, the bootstrap loader fits into the first sector of the boot disk. In addition to the loader, information relating to the BIOS Parameter Block (BPB) should be kept in the boot sector of the disk. The format of the boot INSTALLING MS-DOS Page 3-3 sector is described in Chapter 4. The bootstrap loader loads IO.SYS and MSDOS.SYS into memory. MS-DOS can be located any place in memory above IO.SYS. (IO.SYS can alternately be used to load MSDOS.SYS.) Loading IO.SYS and MSDOS.SYS is simple because these two files must always be the first files on the disk. This means that a bootstrap loader could simply load a series of consecutive sectors into memory. Your bootstrap loader may also read in the first sector of the directory before it loads IO.SYS to verify that these files are the first files on the disk. For more information, see: MS-DOS Programmer's Reference Manual ______ ____________ _________ ______ (Chapter 2) MS-DOS Adaptation Guide (Chapter 4) ______ __________ _____ 8. Assemble, link, and convert to binary (using EXE2BIN) the BOOT.ASM file to produce BOOT.BIN. 9. Format a non-system disk using your MS-DOS development machine. 10. Using the MS-DOS Copy command, copy IO.SYS, MSDOS.SYS, and appropriate version of COMMAND.COM to the formatted disk. 11. Using DEBUG.COM on the development machine, load BOOT.BIN and write it to the first sector of the formatted disk. This can be done as follows: DEBUG -N BOOT.BIN -L (loads BOOT.BIN) -W 100 0 0 1 (writes BOOT.BIN to drive 0 sector 0) -Q Note: More operations may be required depending on how your boot program is organized. For more information, see: Microsoft Macro Assembler Manual (Chapter 4 SYMDEB: _________ _____ _________ ______ A Symbolic Debug Utility The formatted disk should now be bootable by your system. INSTALLING MS-DOS Page 3-4 12. Write the source code for the hardware-specific part of the FORMAT program. The MS-DOS 3.3 version of the FORMAT utility has been structured so that the hardware specific portions have been placed solely in IO.SYS. Minimal work should be required for the OEM use of the MS-DOS 3.2 FORMAT utility. Assemble and link this to the FORMAT.OBJ and FORMES.OBJ files supplied by Microsoft. The modules must be linked in the following order: 2.XX: FORMAT.OBJ+FORMES.OBJ+OEMFOR.OBJ where OEMFOR.OBJ is your hardware-specific module. Use EXE2BIN to convert the OEMFOR.EXE file produced to FORMAT.COM. 3.XX: FORMAT.OBJ+FORPROC.OBJ+FORMES.OBJ+OEMFOR.OBJ+PRINTF.OBJ where OEMFOR is your hardware-specific module. Although the PRINTF.OBJ module is the last module specified, it does not follow the OEM module in the memory image. For more information, see: MS-DOS Adaptation Guide (Chapter 7) ______ __________ _____ OEMFOR.ASM Disk file of sample OEM FORMAT module MS-DOS User's Reference Manual (Format Command, ______ ______ _________ ______ Chapter 3) MS-DOS Programmer's Reference Manual (Chapter 3) ______ ____________ _________ ______ 13. Install the MS-DOS OEM serial number. For information on how this is done, refer to the README.DOC on the distribution diskette. 14. Modify SORTMES.ASM as appropriate. 15. Build SORT executable with SORTBLD.BAT. 16. Modify PRINT source modules as appropriate 17. Build PRINT executable with PRINTBLD.BAT INSTALLING MS-DOS CONTENTS CHAPTER 4 DISK STRUCTURE AND BOOTSTRAP LOADING 4.1 Reserved Area 4-1 4.2 File Allocation Table 4-2 4.3 MS-DOS File System Limits 4-4 4.3.1 Disk Format Identification 4-6 4.4 The role of the Boot Sector 4-7 CHAPTER 4 DISK STRUCTURE AND BOOTSTRAP LOADING MS-DOS disks are divided into four logical data areas. 1. Reserved sectors (boot sector) 2. File Allocation Tables 3. Root directory 4. Data area which may include subdirectories as well as program and data files When creating non-standard disks or non-removable media (such as hard disks), the logical disk which your device _______ driver presents to MS-DOS must conform to the above standard. The physical layout may be completely different. ________ For example, you may want to implement a partitioning scheme on the hard disk so that it can be shared by multiple operating systems. In this case, either the device driver or firmware maps the physical structure into an MS-DOS logical layout. The MS-DOS file system can even be logically implemented within another operating system's file structure. 4.1 RESERVED AREA The reserved area is the first part of the disk and is typically used for boot purposes. Some machines not specifically designed for MS-DOS may use track 0 for special purposes (it may even have a different sector size than the rest of the disk). In this case, the entire track should be marked as reserved so that the device driver will map MS-DOS's logical sector 0 to the beginning of track 1 instead of track 0. It may be difficult to fit the required boot information into a single sector. Note that disk formats using 128- or 256-byte sectors and without any firmware support may DISK STRUCTURE AND BOOTSTRAP LOADING Page 4-2 require several sectors. 4.2 FILE ALLOCATION TABLE The File Allocation Table (FAT) is the most important data structure on the disk. Two copies are usually kept at the OEM's option. (Two copies need not be kept for a virtual RAM disk because, in this case, the media cannot be damaged.) MS-DOS files are allocated in "allocation units" or "clusters". Each cluster is some number of sectors. The number of sectors per allocation unit must be a power of 2 which fits in a byte. Thus, the complete list of possible values is: 1, 2, 4, 8, 16, 32, 64, 128. The FAT is a physical map of the allocation units in the data area of the disk. There is one FAT entry for each allocation unit on the disk plus two reserved entries at the beginning of the FAT. The entries serve as a linked list of pointers. For a complete discussion of FAT structure, refer to Chapter 3 of the MS-DOS Programmer's Reference Manual. ______ ____________ _________ ______ FAT size can be determined by the following formula: FAT = Q * ( T - R - D + 2) -------------------- Q * N + ( A * S ) FAT is the number of sectors needed for one FAT and will usually not be an integer. It must be rounded up to the next integer value. Q is the number 1.5 for 12-bit FAT entries and 2.0 for 16-bit FAT entries. T is the total number of sectors on the disk. R is the number of reserved sectors. D is the number of root directory sectors (there must be 32 bytes for each directory entry). A is the number of sectors per cluster or allocation unit. N is the number of file allocation tables on the disk. S is the number of bytes per sector. MS-DOS 3.x can use 16-bit FAT pointers whenever the total DISK STRUCTURE AND BOOTSTRAP LOADING Page 4-3 number of clusters on the disk exceeds 4085 (=4096-10; two are reserved at the beginning, and eight are reserved at the end). Although the FAT entries are 16 bits, the present software only works with 15 bits (up to 32766 clusters). ____________________________________________________________ | | | Important | | | | Be careful when reducing cluster size as it can cause | | significant performance degradation. Reducing cluster | | size results in increased fragmentation, a larger FAT | | to buffer (increasing the number of disk accesses); and | | increasing the FAT entries from 12 to 16-bit expands | | the FAT size by 33%. | | | |__________________________________________________________| The FORMAT program will create a proper FAT. The FAT has an entry for each allocation unit in the data area of the disk. It also contains two extra entries at the beginning. These represent reserved clusters. The first cluster of the data region of the disk is cluster 2. The first (0th cluster) of these two reserved entries can be used to indicate the format of the disk. Only the low 8 bits are used, and this byte is often referred to as the FATID byte. The high 4 bits (high byte if a 16-bit FAT) of this first cluster are all set (=1). The FATID byte is restricted to be in the range 0F8H to 0FFH, inclusive (8 possible values). The FATID byte is also an end-of-file (EOF) mark. If a FAT chain contains a zero entry (which should never happen), it will point to this EOF marker. The second (1st cluster) of these two reserved entries is always 0FFFH (0FFFFH for a 16-bit FAT), which is an end-of-file mark. DISK STRUCTURE AND BOOTSTRAP LOADING Page 4-4 Figure 4.1 illustrates the first two clusters of a 12-bit File Allocation Table. FAT BYTE 00 01 02 03 XXH XXH XXH XXH----->Byte 3 || || || Middle 4 bits | || High and middle 4 bits of of cluster 0 | || cluster 1 (always F) | | High 4 bits of Low 4 bits of | cluster 0 (always F) cluster 0 | | | Low 4 bits of cluster |------------------| 1 (always F) | FATID BYTE Figure 4.1. First Two Entries of the FAT (12-bit) 4.3 MS-DOS FILE SYSTEM LIMITS The following figure shows the file storage limitations within MS-DOS. | MS-DOS 2.x | Both | MS-DOS 3.x _______________|______________|_____________|_______________ |FAT entry size |12 bits | |12 or 16 bits | |Sector size | |64b-32Kb | | |No. of Sectors | |Max of 64K | | |Cluster size | |1-128 sectors| | |Max. disk size |4085 clusters |64K sectors |32766 clusters| |Max. file size | |Disk size | | ________________|______________|_____________|______________| All ranges in the table are inclusive. As well as the above limitations, there are also various limits as noted below: 1. FAT entry size. This is the only file storage limit difference between MS-DOS 2.XX and 3.XX; it significantly increases the maximum number of clusters and hence the maximum disk size allowed. MS-DOS 3.x determines whether a 12- or 16-bit FAT is in use by calculating the number of disk clusters from the BPB. If the number of clusters is less than or equal to 4085, a 12-bit FAT is in use; otherwise, a 16-bit FAT is assumed. A 16-bit FAT cannot be used if the total number of clusters is less than DISK STRUCTURE AND BOOTSTRAP LOADING Page 4-5 or equal to 4085. Some existing MS-DOS applications (such as copy protection schemes and disk maintenance utilities) bypass MS-DOS and manipulate the FAT directly. These existing applications will cause problems with 16-bit FATs until the applications are updated to recognize the 16-bit FATs. 2. Sector Size. Must be a multiple of 64 bytes. 3. No. of Sectors. The number of sectors is limited to 64K because 16-bit sector numbers are passed to the device drivers. 4. Cluster Size. The cluster size (bytes/cluster = sectors/cluster * bytes/sector) must be less than 64K because MS-DOS uses 16-bit arithmetic. Sectors/Cluster must be a power of 2 in the range 1-128. Excessively small cluster sizes can seriously degrade performance. Refer to the MS-DOS ______ Programmer's Reference Manual for sample disk ____________ _________ ______ formats. 5. Max. Disk Size. MS-DOS 2.XX: Lesser of 4085 clusters or 64K sectors (For example, 64K*512 byte sectors = 32Mb disk). MS-DOS 3.XX: Lesser of 32766 clusters or 64K sectors. The total number of sectors is limited to 64K due to the use of 16-bit arithmetic. The maximum number of possible clusters is calculated by the following: FAT entry size (2 -10 Reserved) Reserved: 8 FAT ID/EOF (F8-FF) 2 RESERVED (0,1) ------------------------------------------------------------ | | | Note | | | | However, some MS-DOS utilities (such as Chkdsk and | | Recover) restrict the total FAT size to 32K entries, | DISK STRUCTURE AND BOOTSTRAP LOADING Page 4-6 | hence the MS-DOS 3.x limit of 32,766 clusters and not | | 65,525 (216-11). | | | |__________________________________________________________| There are 10 MS-DOS reserved FAT entries; two at the front of the FAT, and eight at the end: DISK STRUCTURE AND BOOTSTRAP LOADING Page 4-7 4086 = 4K -10 32766 = 32K -2 The 8 reserved clusters are in the range 65528-65536. 6. Max. File Size. Files cannot be split across disks; therefore, the maximum file size is normally the maximum disk size. The file size is also restricted by a 32-bit file pointer. This means that the maximum possible file size is 4 gigabytes: 32 4 million K, 2 -1 4.3.1 Disk Format Identification Beginning with MS-DOS 2.0, Microsoft is promoting the use of a media descriptor table in the boot sector. This table contains both a physical description (number of sectors, sides, tracks, etc.) and a logical description (number of FATs, directory entries, etc.) of the disk layout. The media description table allows MS-DOS to accommodate future floppy disk formats, or formats defined by other manufacturers but not generated by your FORMAT utility. Your device driver should assume that the media description table exists if the first byte of the boot sector is the first byte of a 3-byte (near) jump or a 2-byte jump. DISK STRUCTURE AND BOOTSTRAP LOADING Page 4-8 4.4 THE ROLE OF THE BOOT SECTOR Typically, the system ROM will load the reserved (boot) sector or sectors into memory at power-up or restart. We recommend that the boot sector do the following: 1. It should read the first sector of the directory and verify that the first two files on the disk are IO.SYS and MSDOS.SYS, in that order. You may choose to have your FORMAT utility generate different boot sectors for each disk format. Or, you may create a universal boot sector to read the media description table and determine where to find the first directory sector both logically and physically. 2. If the boot code does not find the MS-DOS files in the directory, then the boot sector should prompt the operator that an attempt has been made to boot from a non-bootable disk. You determine how the user should continue ("Strike any key" or "Turn power off"). 3. The boot sector must read in the IO.SYS and MSDOS.SYS files. Alternatively, the boot sector may read in only IO.SYS, and IO.SYS may then read in MSDOS.SYS. Only IO.SYS needs to be contiguous on the disk. The boot sector must know or calculate where those files physically begin on the disk (right after the last directory sector) and how long they are (contained in directory entries). You must code (or calculate) the location at which they should be loaded into memory in the boot sector. 4. The boot sector must transfer control to your entry point in IO.SYS. The boot sector does not load COMMAND.COM, as it will be loaded by SYSINIT. The SYS command allows users to transfer the operating system onto a formatted disk that contains no files or contains an old version of the operating system of equal or greater size. For the MS-DOS 2.XX version on the IBM PC, the SYS command was modified to transfer MS-DOS 2.XX system files onto old 1.XX disks. The new MSDOS.SYS can be placed on the disk in a non-contiguous format. (IO.SYS is still contiguous because the new IO.SYS is smaller than the DISK STRUCTURE AND BOOTSTRAP LOADING Page 4-9 combined sizes of the old IO.SYS and MSDOS.SYS.) The boot sector is only responsible for loading IO.SYS, although it must check that MSDOS.SYS is the second file on the disk. Therefore, IO.SYS may load a non-contiguous MSDOS.SYS. The logic to facilitate checking through the FAT entries must be added to IO.SYS because the logic normally resides in the not-yet-loaded MSDOS.SYS. The logic resides in the installation part of IO.SYS so that it will be overwritten when MSDOS.SYS is loaded. This technique should only be used to use the SYS command to transfer a new, bigger MS-DOS onto an old disk. It is not useful if you do not have old disks to support in the field. Note that the various FAT entries for a non-contiguous MSDOS.SYS may reside in different FAT sectors making it necessary to read more than just the first FAT sector into memory. There is an example of a boot sector on the OEM Sample MS-DOS Implementation Diskette. DISK STRUCTURE AND BOOTSTRAP LOADING CONTENTS CHAPTER 5 RESIDENT DEVICE DRIVERS 5.1 Introduction 5-1 5.2 Bit 4 5-3 5.3 Installation of Device Drivers 5-5 5.4 The CLOCK Device 5-5 5.5 INIT (Command Code 0) 5-6 5.6 Media Check 5-7 5.7 DMA Boundary Violation 5-9 CHAPTER 5 RESIDENT DEVICE DRIVERS ------------------------------------------------------------ | | | Note | | | | Chapter 2, "Device Drivers," in the MS-DOS Programmer's | | Reference Manual contains a description of MS-DOS | | device drivers. Additional information applicable to | | OEM is included here. | | | ------------------------------------------------------------ 5.1 INTRODUCTION The IO.SYS file is composed of the "resident" device drivers. This forms the MS-DOS Basic Input Output System (BIOS), and these drivers are called upon by MS-DOS to handle I/O requests initiated by application programs. One of the most powerful features of MS-DOS is the ability to add new devices such as printers, plotters, or mouse input devices without rewriting the BIOS. The MS-DOS BIOS is "configurable;" that is, new drivers can be added and existing drivers can be pre-empted. Non-resident device drivers may be easily added by a user at boot time via the "DEVICE =" entry in the CONFIG.SYS file. In this section, these non-resident drivers are called "installable" device drivers to distinguish them from drivers in the IO.SYS file, which are considered the resident drivers. At boot time, a minimum of five resident device drivers (four character devices and one block device) must be present. These drivers are in a linked list: the header of each one contains a DWORD pointer to the next. The last driver in the chain has an end-of-list marker of -1, -1 (all bits on). Each driver in the chain has two entry points: the strategy entry point and the interrupt entry point. MS-DOS 2.XX/3.XX does not take advantage of the two entry points: it calls RESIDENT DEVICE DRIVERS Page 5-2 the strategy routine, then immediately calls the interrupt routine. The dual entry points facilitate future multitasking versions of MS-DOS. In multitasking environments, I/O must be asynchronous; to accomplish this, the strategy routine will be called to (internally) queue a request and return quickly. It is then the responsibility of the interrupt routine to perform the I/O at interrupt time by getting requests from the internal queue and processing them. When a request is completed, it is flagged as "done" by the interrupt routine. MS-DOS periodically scans the list of requests looking for those that are flagged as done, and "wakes up" the process waiting for the completion of the request. When requests are queued in this manner, it is no longer sufficient to pass I/O information in registers, since many requests may be pending at any time. Therefore, the MS-DOS 2.x/3.x device interface uses "packets" to pass request information. These request packets are of variable size and format, and are composed of two parts: 1. The static request header, which has the same format for all requests. 2. A section that has information specific to the type of request. A driver is called with a pointer to a packet. In multitasking versions, this packet will be linked into a global chain of all pending I/O requests maintained by MS-DOS. The 2.XX and 3.XX versions of MS-DOS do not implement a global or local queue. Only one request is pending at any one time. The strategy routine must store the address of the packet at a fixed location, and the interrupt routine (which is called immediately after the strategy routine) should process the packet by completing the request and returning. It is assumed that the request is completed when the interrupt routine returns. To make a device driver that SYSINIT can install, a .BIN (core image) or .EXE format file must be created with the device driver header at the beginning of the file. The link field should be initialized to -1 (SYSINIT fills it in). Device drivers that are part of the BIOS should have their headers point to the next device in the list and the last header should be initialized to -1,-1. The BIOS must be a BIN (core image) format file produced by using the utility EXE2BIN. .EXE format installable device drivers may be used in RESIDENT DEVICE DRIVERS Page 5-3 non-IBM versions of MS-DOS before 3.0. The reason for this restriction is that on the IBM PC, the .EXE loader is located in COMMAND.COM, which is not present at the time that installable devices are being loaded. The attribute field and entry points must be set correctly. If the device is a character device, the name field must be filled in. (This name can be any 8-character legal filename). If it is a block device, SYSINIT will fill in the correct unit count. SYSINIT always installs character devices at the start of the device list, so if you want to install a new CON device, simply name it CON. The new one will be placed ahead of the old one in the list and will pre-empt the old one because the search for devices stops on the first match. Be sure to set the standard input (sti) and standard output (sto) bits on a new CON device. ------------------------------------------------------------ | | | Note | | | | Since SYSINIT may install the driver anywhere, be | | careful when coding FAR memory references. You | | should NOT expect that your installable driver will be | | located in the same place every time. This does not | | apply for the resident device drivers. | | | |__________________________________________________________| 5.2 BIT 4 In the MS-DOS Programmer's Reference Manual, bit 4 of the ______ ____________ _________ ______ device driver header format is defined as reserved. It actually has special meaning. Bit 4, the special bit, applies to CON drivers. The new interface supports many new features, but it is slower than MS-DOS 1.x 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. For example, you should make one XENIX-style system call to output x number of bytes rather than x system calls to output one byte each. RESIDENT DEVICE DRIVERS Page 5-4 Putting a device channel in raw mode provides an even faster way to output characters. (See the Glossary for an explanation of "raw" mode.) Bit 4, has been implemented to alleviate the CON output speed problem for older programs that use system calls 01H to 0BH to output large amounts of data. If this bit is 1, the device is CON and an Interrupt 29H has been implemented, where the 29H handler is defined as follows: CONSOLE OUTPUT via INT 29H handler Input: Character in AL Function: Output the character in AL to the screen at the current cursor location. Output: None Registers: All registers except BX must be preserved. No registers except AL have a known or consistent value. If a character device implements the special bit, the driver must install an address at the correct location in the interrupt table for Interrupt 29H. Only one device driver can have the special bit set in the system. There is no check to ensure this state. ____________________________________________________________ | | | Warning | | | | This feature may not be supported in future versions of | | MS-DOS. Any application (not device driver) that uses | | Interrupt 29H directly will not work on future versions.| | In addition, the console device driver must be tested | | with bit 4 not set to ensure that it will work with such | | future versions of MS-DOS. | | | ____________________________________________________________ The headers of resident drivers should point to the next device in the list and the last header should be initialized to -1,-1. IO.SYS must be a .COM format file. RESIDENT DEVICE DRIVERS Page 5-5 5.3 INSTALLATION OF DEVICE DRIVERS MS-DOS 2.XX/3.XX allows new device drivers to be installed dynamically at boot time. This is accomplished by the SYSINIT module(s) supplied by Microsoft, which read(s) and processes the CONFIG.SYS file. The resident driver source file (IO.ASM) is assembled and linked to the appropriate SYSINIT module(s) and SYSIMES.OBJ. The resultant .EXE file must be converted via EXE2BIN to create the file IO.SYS. This should be the first file that appears on the system disk. When block drivers are installed, the logical drive letters are assigned in list order; thus, the driver that will 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 four character devices defined at boot time. The first four character devices must be as follows: 1. Standard input, standard output, and standard error output (CON) 2. Standard auxiliary input and output (AUX) 3. Standard list output (PRN) 4. Date/time (CLOCK) The linked list of device drivers must look like this: ->CON->AUX->PRN->CLOCK->any other block or character devices 5.4 THE CLOCK DEVICE The CLOCK device is used by MS-DOS 2.XX/3.XX for marking file control blocks and directory entries with date and time as well as providing date/time services to application programs. It is unique in that MS-DOS will read or write a 6-byte sequence which encodes the date and time. A write to this device will set the date and time and a read will get the date and time. Figure 5.1 illustrates the binary date and time format used by the CLOCK device. RESIDENT DEVICE DRIVERS Page 5-6 byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 +--------+--------+---------+--------+--------+---------+ | | | | | | | |days since 1-1-80| minutes | hours | sec/100| seconds | |low byte|hi byte | | | | | +--------+--------+---------+--------+--------+---------+ Figure 5.1. CLOCK Device Format 5.5 INIT (COMMAND CODE 0) One of the functions defined for each device is INIT. This routine is called only when the device is installed. It is used for initializing character and block devices. Figure 5.2 illustrates the format of INIT. +------------------------------------+ | 13-BYTE Request Header | +------------------------------------+ | BYTE # of units | +------------------------------------+ | DWORD Break Address | +------------------------------------+ | DWORD Pointer to BPB array | | (not set by character devices) | +------------------------------------+ Figure 5.2. INIT Format For resident character devices:___ ________ _________ _______ No parameters are passed, and none are returned. For resident block drivers:___ ________ _____ _______ Unlike character device drivers, block device drivers must return a number of parameters. The following data are returned: 1. The number of units defined by this block device driver. This is used to determine logical device names. If the current maximum logical device letter is F at the time of installation, and the INIT routine returns 4 as the number of units, then those units will have the logical names G, H, I and J. This mapping is determined by the position of RESIDENT DEVICE DRIVERS Page 5-7 the driver in the device list and the number of units defined by the device (stored in the first byte of the device name field). You must return this number at offset 13D in the INIT call, even though the number of units is stored in the device header. 2. A DWORD pointer to an array of WORD offsets to BPBs (BIOS Parameter Blocks). There must be one entry for each unit defined by the device driver. If the device driver defines two units, then the DWORD pointer points to the first of two one-word offsets which, in turn, point to BPBs. If both BPBs are the same, this will allow you to save space by entering two offsets to the same location. The BPB is used by MS-DOS to create an internal DOS structure. The BPBs that are returned by the resident device drivers are scanned to determine the largest sector size. This number is used to set the cache buffer size. Installable block devices cannot have larger sector sizes than those defined by the resident drivers. For this reason, you may want to use dummy BPBs to reserve space. Use an invalid media byte so that when you later report the correct BPB for the unit. MS-DOS will build the correct internal DOS structure for the particular drive unit. 5.6 MEDIA CHECK The MEDIA CHECK function is called when there is a pending drive access call other than a file read or write (i.e access to the "FILENAME space" - Open, Close, Get_disk_size, INT 25H, INT 26H, etc.). Its purpose is to determine whether the media in the drive has been changed. Note that the previous media ID byte is passed to the device driver. Although the old media ID byte is the same as the new one, the disk may have been changed and a new disk may be in the drive; therefore, the FAT, and directory and data sectors for the unit are invalid. MS-DOS 3.XX imposes stricter conditions than MS-DOS 2.XX on when media changes are allowed. This can lead to MEDIA CHECK routines that seemed to work correctly under MS-DOS 2.XX causing problems under MS-DOS 3.XX. MS-DOS performance is greatly improved if MEDIA CHECK uses a doorlock or some other detection method so that it can guarantee that no disk change has occurred; then MS-DOS does not have to reread the FAT before each directory access. MEDIA CHECK can directly use the door-lock mechanism to return "Disk not changed." However, the door-lock mechanism RESIDENT DEVICE DRIVERS Page 5-8 indicating that the door has been opened does not necessarily mean that the disk has been changed, since the user could have reinserted the same disk. MEDIA CHECK routines that return "Disk has been changed" just because the door has been opened will cause problems under MS-DOS 3.x, but not under MS-DOS 2.XX. The recommended behavior for MEDIA CHECK is to return as follows: Disk has not been changed - whenever the door lock indicates that the door has not been opened Don't know - under all other circumstances It is possible for MEDIA CHECK to try to determine whether a disk has really been changed by checking the Volume ID; however, many disks have no Volume ID. Therefore, it is safer and quicker for MEDIA CHECK to simply return "Don't know." The action that MS-DOS takes depends on the state of its internal file storage buffers. In general, if "Don't know" is returned when MS-DOS has data in its internal buffers (data that needs to be written out), MS-DOS will assume no disk change has occurred. Otherwise, with empty buffers or all buffers "clean", MS-DOS assumes the disk has been changed. The possible problems caused by an incorrect MEDIA CHECK routine can be checked as follows: 1. Load MS-DOS 3.XX 2. Ensure the disk is write-protected 3. COPY FILE1 FILE2 4. Write Protect Error from MS-DOS 5. Remove the write protection from the disk 6. Reinsert the disk in the drive 7. Press "R" to cause MS-DOS to retry 8. Copy success message If an incorrect MEDIA CHECK routine is in use, the Dir command will show FILE2 with a size of zero bytes, and Chkdsk will report "lost clusters." Note that the copy process always returns the success message even with an incorrect MEDIA CHECK routine. The above test should also be repeated with a "Drive Not Ready" error condition instead of the Write Protect error. The same symptoms will be displayed. For more information on MEDIA CHECK, refer to the MS-DOS ______ Programmer's Reference Manual.____________ _________ _______ RESIDENT DEVICE DRIVERS Page 5-9 5.7 DMA BOUNDARY VIOLATIONS Some OEMs check for any DMA boundary violations on disk operations. If a DMA boundary violation error is detected then action is taken to prevent this error from being reported to the DOS. The sample IO.SYS handles the problem in the following way. The operation is tried and if a DMA boundary violation is reported, then a flag (in this case bl) is set to indicate that we need to do a memory swap to avoid the boundary problem. The sector of data that causes the DMA boundary violation is transfered into an internal buffer that belongs to IO.SYS and then is copied into the buffer specified in the original request. In other words, the request is broken into several pieces consisting of a request for the data up to the DMA boundary violation, then the one sector of data that causes the DMA boundary violation (in the sample IO.SYS SwapMemory routine is responsible for doing this), and then the rest of the request as specified by the original disk operation. Applications do not depend on this feature in any direct way. However, if you do not implement the DMA boundary checking then it would be possible for an application to get an INT24 error because of the DMA boundary problem and thus behave differently depending on how the BIOS was implemented. CHAPTER 6 SYSINIT AND MS-DOS INITIALIZATION 6.1 Introduction 6-1 6.2 The Role of SYSINIT 6-3 6.3 COMMAND.COM 6-5 CHAPTER 6 SYSINIT AND MS-DOS INITIALIZATION 6.1 INTRODUCTION In addition to implementing the resident drivers and performing any hardware initialization, the IO.ASM code must initialize certain external variables. These variables are declared public in the SYSINIT module(s) to which the IO.OBJ module is linked. The public variables and their functions are described below. CURRENT_DOS_LOCATION WORD This is the paragraph location where the bootstrap loader (or, optionally, IO.SYS) has loaded MSDOS.SYS into memory. Typically, MSDOS.SYS is located immediately after IO.SYS. FINAL_DOS_LOCATION WORD Since SYSINIT immediately relocates itself to high memory, there will be a hole right after the resident drivers. By telling SYSINIT the paragraph where you want it to relocate MSDOS.SYS, you can fill up this hole plus overlay any code that IO.SYS used for hardware initialization at boot time. SYSINIT will move MSDOS.SYS down to this location, conserving space. This location also defines where memory starts for MS-DOS. DEVICE_LIST DWORD IO.SYS must tell SYSINIT where the linked list of device drivers begins. This is the location of the CON device driver header; the information is passed to MS-DOS so that the drivers can be accessed. SYSINIT AND MS-DOS INITIALIZATION Page 6-2 MEMORY_SIZE WORD This word is the paragraph number of the highest location in RAM. If you do not initialize MEMORY_SIZE, SYSINIT will do a memory scan to determine the amount of memory. It does this by reading every 16 bytes starting at 32K, writing an arbitrary pattern, reading it back for a match, and returning the original value. It stops when it gets a mismatch. If your system has parity memory, you must declare this value, since writing to nonexistent memory will cause a parity error. MS-DOS should be implemented in systems with contiguous memory. DEFAULT_DRIVE BYTE If you can boot MS-DOS from several drives, you must tell SYSINIT which drive you booted from so it can find CONFIG.SYS and COMMAND.COM. This variable should be set as follows: drive A = 1, drive B = 2, etc. If DEFAULT_DRIVE is not set, the default drive (drive A) is assumed. BUFFERS BYTE This is the default number of sector buffers for the system. The BUFFERS value may be overridden by the user in the CONFIG.SYS file. On versions of MS-DOS up to 3.1, the default number of buffers is 2. On versions of MS-DOS after 3.1, 3 buffers will be allocated if there is a floppy drive in the hardware configuration with a capacity greater than 360KB. Beginning with 3.3, if memory size is greater than 128K, then 5 buffers will be allocated, and if memory is greater than 256K 10 will be allocated; if memory is greater than 512K, 15 buffers will be allocated. The value specified for the number of buffers must be greater than or equal to 1. FILES BYTE This is the default number of open files that system calls 2FH-62H can access. This value may be overridden by the user in the CONFIG.SYS file. Its default setting in SYSINIT is 8. Values of less than 5 are ignored. The entry point in SYSINIT should be defined as a FAR label in IO.SYS as follows: EXTRN SYSINIT:FAR After IO.SYS code has performed any hardware initialization and has set the above external variables, it should do a FAR jump to this label. SYSINIT AND MS-DOS INITIALIZATION Page 6-3 You must provide a FAR procedure in the IO.ASM code which is not subject to being overlayed when SYSINIT relocates MS-DOS. This procedure is called RE_INIT. It should be declared as follows: RE_INIT: PROC FAR ........ ........ RET RE_INIT ENDP The RE_INIT procedure is called by SYSINIT after MS-DOS is installed. On entry, DS:0 points to a 100H-byte program segment prefix which represents the Program Segment Prefix of SYSINIT and IO.SYS taken together. This is not a normal program because no memory is allocated to it; therefore, if you allocate and load or Exec, you may overlay this block. SYSINIT is located in the top 10K of memory. Do not write __ ___ _____ there. The space above the 100H byte header at DS:100 is_____ available for temporary use during RE_INIT. The RE_INIT routine can be used to perform functions such as to print headers and read files, and it is handy for IO.SYS debugging. If you don't need to use this procedure, simply do a return (RET). Note that starting with MS-DOS 3.XX, RE_INIT may not use FCB system calls. ------------------------------------------------------------ | | | Warning | | | | RE_INIT must not change any registers or flags. | | | |__________________________________________________________| Beginning with MS-DOS 3.2, another FAR procedure must be provided in IO.ASM. The name of this procedure is STACKINIT. The purpose of this procedure is to initialize a hardware stack switching algorithm. If some of the hardware interrupt handlers in the ROM BIOS of the OEM hardware system are stack intensive, then this initialization routine would be used to direct the processing of the hardware interrupt handlers to another portion of code in IO.ASM. This code will save the current stack setup and switch stacks to an internal space on occurrence of a hardware interrupt. When the stack has been switched the original interrupt handler is called. The rest of the interrupt handling will use the internal stack and not the stack that was in use when the interrupt occurred. When the interrupt handler returns the stack is set to its original state. The advantage of this feature is that there is greater system reliability since a dedicated stack space is being used for interrupt handling. The OEM should determine which hardware interrupt handlers are stack intensive and redirect only those interrupts to the stack switching code in IO.ASM. This procedure is similar to the FAR procedure RE_INIT in that the code is not subject to being overlayed when SYSINIT relocates MS-DOS. The procedure STACKINIT should be declared in the same fashion as RE_INIT. After MS-DOS is installed, SYSINIT calls the procedure STACKINIT. If this procedure is not going to be used, then simply do a return or the OEM can assemble SYSINIT with the conditional STACKSW set to FALSE. On entry to this routine, there are three data variables that are available. These pieces of data reside in the SYSINIT segment. The following declarations should be made in IO.ASM to access these variables. SYSINITSEG SEGMENT PUBLIC 'SYSTEM_INIT' EXTRN STACK_ADDR:DWORD EXTRN STACK_SIZE:WORD EXTRN STACK_COUNT:WORD SYSINITSEG ENDS These variables are set by SYSINIT and can be changed by using the STACKS option in CONFIG.SYS. The full syntax of the STACKS option is: STACKS=STACK_COUNT,STACK_SIZE where STACK_COUNT is the number of stacks (range 8 to 64, default 9) STACK_SIZE is the stack size (range 32 to 512 bytes, default 128) The variable STACK_ADDR is the FAR address of the space that SYSINIT has allocated for the internal stacks. Beginning with MS DOS 3.3, there is a special case for STACKS=0,0. This will result in no dynamic stacks being provided. DOS will not intercept any interrupts and will only use it own standard stack. ____________________________________________________________ | | | Warning | | | | STACKINIT must not change any registers or flags. | | | ------------------------------------------------------------ 6.2 THE ROLE OF SYSINIT The following steps illustrate the role of SYSINIT in MS-DOS initialization: 1. When SYSINIT gains control from the IO.SYS initialization code, it determines the size of memory (performing a scan if requested, based on value of MEMORY-SIZE) and, based on the highest paragraph and the size of SYSINIT, it relocates itself to high memory. SYSINIT AND MS-DOS INITIALIZATION Page 6-4 2. Running in high memory, SYSINIT moves MSDOS.SYS from the CURRENT_DOS_LOCATION to the FINAL_DOS_LOCATION as specified by IO.SYS (see the memory maps in Section 6.3, "COMMAND.COM"). 3. SYSINIT does a FAR call to MS-DOS. MS-DOS has initialization code which steps through the linked list of device drivers and performs the INIT call to each. The copyright message is then printed out on the screen. 4. After initializing the resident devices, building drive parameter blocks for the resident block devices, and installing a sector buffer, MS-DOS does a FAR return to SYSINIT. During MS-DOS initialization, MS-DOS examines the BIOS Parameter Blocks (BPBs) returned by the INIT call to the block devices. It uses the largest sector size it finds as the default buffer size for all buffers. For this reason, the initial BPBs may be used to reserve space for an installable device with a larger sector size rather than reflecting the format of the installed disk. In this case, these dummy BPBs must have media bytes that do not have the same value as those used in real BPBs. 5. SYSINIT calls RE_INIT in IO.ASM to allow the OEM to print headers or handle any other initialization. ------------------------------------------------------------ | | | Warning | | | | Do not attempt to modify memory. | | | |__________________________________________________________| 6. After IO.SYS returns control to SYSINIT, SYSINIT attempts to open the CONFIG.SYS file. If found, this file is loaded in memory and all characters are turned to uppercase. It is then parsed looking for keywords such as DEVICE, BUFFERS, and SHELL. Any new devices are loaded, added to the linked list, and installed via the INIT call. Character devices are added to the front of the list, and new block devices are added to the end. Thus, a new CON device can supplant an existing resident CON device. This provides the facility to reconfigure IO.SYS except for the Resident Disk Block device driver. SYSINIT AND MS-DOS INITIALIZATION Page 6-5 7. SYSINIT allocates all of the memory it needs to protect the buffers, installed device driver code, and IO.SYS. It sets the "owner" of the memory to a special value to ensure that this block of memory is never deallocated. 8. SYSINIT closes all file handles, and then reopens CON, AUX, and PRN. This enables a new CON, AUX or PRN device to replace the resident devices. 9. SYSINIT allocates memory for the buffers. 10. SYSINIT allocates memory for hardware stacks and calls STACKINIT to initialize the hardware stack switching algorithm (only in versions of DOS 3.2 and later). 11. SYSINIT executes COMMAND.COM. 12. COMMAND.COM allocates memory for its transient portion and moves it. MS-DOS is now up and running. 6.3 COMMAND.COM During its initialization, COMMAND.COM allocates memory for its transient part and reloads it. The transient part of COMMAND, which contains the internal commands (Copy, Dir, Date, Time, etc.), resides in unprotected memory when a user's program is loaded into the Transient Program Area (TPA). It will be overlaid by programs needing the space. When a user program terminates to the COMMAND resident, the transient is checked to see if reloading is necessary. SYSINIT AND MS-DOS INITIALIZATION Page 6-6 Each of the following memory maps represents a step in the MS-DOS initialization process. +-----------------------------+ | | High memory | | | | | | +-----------------------------+ Loaded at arbitrary | Bootstrap loader | location by system ROM +-----------------------------+ XX:00 | | | | | | | | | | | | | | | | | | | | | | +-----------------------------+ Segment 40H | Interrupt Vector Table | +-----------------------------+ -0:00 Memory organization in an MS-DOS system after the system ROM has loaded the boot sector. SYSINIT AND MS-DOS INITIALIZATION Page 6-7 +-----------------------------+ | | High memory | | | | +- - - - - - - - - - - - - - -+ | Spent bootstrap loader | +- - - - - - - - - - - - - - -+ | | | | | | +-----------------------------+ | | MS-DOS disk operating | MSDOS.SYS | system in temporary | | location | | +-----------------------------+ Microsoft-supplied | SYSINIT | system initialization +- - - - - - - - - - - - - - -+ module (part of IO.SYS) | | | IO.SYS | IO.SYS (may begin at +-----------------------------+ any location) | Interrupt Vector Table | +-----------------------------+ Memory after bootstrap loader loads IO.SYS and MSDOS.SYS. SYSINIT AND MS-DOS INITIALIZATION Page 6-8 +-----------------------------+ | SYSINIT | High memory | relocates itself to highmem | +-----------------------------+ | | | | | | | | | | +-----------------------------+ | | | MS-DOS structures, buffers, | SYSINIT loads installable | hardware stack space, | drivers and buffers here | and installable drivers | +-----------------------------+ | | | MSDOS.SYS relocated by | SYSINIT moves MS-DOS | SYSINIT to fill hole in | down to OEM-designated | memory. | FINAL_DOS_LOCATION | | +-----------------------------+ | IO.SYS | +-----------------------------+ | Interrupt Vector Table | +-----------------------------+ Memory during system initialization performed by SYSINIT module. SYSINIT AND MS-DOS INITIALIZATION Page 6-9 +-----------------------------+ | COMMAND.COM | High memory | (transient) | +-----------------------------+ | | Start of TPA will vary | Transient Program Area | with # of drivers, | (TPA) | buffers, etc. +-----------------------------+ | COMMAND.COM (resident) | COMMAND.COM loads its +-----------------------------+ transient part into top | | of largest available | MS-DOS structures, buffers | memory | hardware stack space, | | and installable drivers | +-----------------------------+ | | | | | MSDOS.SYS | | | | | +-----------------------------+ | | | IO.SYS | | resident device drivers | +-----------------------------+ | Interrupt Vector Table | +-----------------------------+ Memory after SYSINIT installs command interpreter. This represents the normal configuration during MS-DOS operation. SYSINIT AND MS-DOS INITIALIZATION CONTENTS CHAPTER 7A WRITING THE FORMAT MODULE FOR MS-DOS 3.20/3.21 7.1 Introduction 7-1 7.2 Format Modules and the ES Register 7-9 7.3 Changing the Logical Format of Disks 7-9 CHAPTER 7B WRITING THE FORMAT MODULE MS-DOS 3.20/3.21 HIGHLIGHTS OF CHANGES IN 3.2X OVER PREVIOUS 2.XX FORMAT VERSION: o FORMAT is now designed to be an .EXE file. o The FBIGFAT variable has been introduced for 16-bit FAT support. o ALLOCATEFAT routine allows space for the FAT to be dynamically allocated. o Hardware specific functionality assumed to be provided by device drivers. HIGHLIGHTS OF CHANGES IN 3.20 OVER PREVIOUS FORMAT VERSIONS: The intention of the MS-DOS 3.2 FORMAT utility is to reduce the amount of OEM work and also move any machine dependencies to the device drivers (software BIOS). The following are the new features of the MS-DOS 3.2 FORMAT utility: o FORMAT is now designed to be hardware independent. The FORMAT utility no longer makes calls directly to the ROM BIOS to perform the format operation. The direct calls to the ROM BIOS have been replaced with MS-DOS system calls (Generic IOCTL's) that perform the necessary format functions. The responsibility for interacting with the ROM BIOS to deal with the formating functions is now placed in the OEM's device drivers. o The current head and cylinder being formated is displayed in the layout: Head: %d Cylinder: %d o Two new switches have been added to FORMAT. The new switches are: /N:xx - Specifies the number of sectors/cylinder on the media. /T:yy - Specifies the number of tracks on the media. These two options will only be useful if the ROM BIOS has support to deal with changing of the disk drive parameters. o FORMAT will no longer format the default drive if no drive was specified on the command line. 7.1 INTRODUCTION The MS-DOS Format command formats a new disk, clears the FAT and directory, and optionally copies system files and COMMAND.COM to the new disk. The 3.2X Format utility no longer requires the hardware specific code supplied by the OEM in previous versions. Instead, Format relies on the drive device driver to provide the functionality required to format a track on that drive. The Format utility uses a GENERIC_IOCTL function request to access the drive device driver to format a track on the drive. If the device driver does not support a format track function the Format utility will not be able to format the drive. FORMAT is shipped in two hardware-independent object modules. These must be linked to a system configuration dependant module written by the OEM. The following section describes the routines required in this module. A sample OEM format module is included on the MS-DOS release disks to assist in writing these routines. The syntax for the Format command is: Format drive: [/switch1][/switch2]...[/switch16] "drive:" is a legal drive specification. As many as 16 legal switches can be included in the command line. 7.2 CODE AND DATA FROM THE OEM As the OEM may need to tailor the FORMAT module for a particular system configuration the OEM must supply the routines and data items which are specific to that configuration. The OEM should produce a module, eg. OEMFOR.ASM, which contains the following (NEAR) data items; SWITCHLIST DOSFILE BIOSFILE and the following (NEAR) routines; OEMDONE WRITEBOOTSECTOR CHECKSWITCHES LASTCHANCETOSAVEIT The detailed description of the data items required to be declared public in the OEM's module is as follows; SWITCHLIST A string of bytes. The first byte is count n, followed by n characters that are the switches to be accepted by the command line scanner. Alphabetic characters must be in uppercase (the numeric characters 0-9 are allowed). The last six switches, normally "/N","/T","/C","/O", "/V" and "/S", have predefined meanings. The "/S" switch is the switch that causes the system files IO.SYS, MSDOS.SYS, and COMMAND.COM to be transferred to the disk after it is formatted, thus making a system disk. The switch can be some letter other than "S", but the last switch in the list is assumed to have the meaning "transfer system," regardless of what the particular letter is. The second to the last switch, "/V", causes FORMAT to prompt the user for a volume label after the disk is formatted. As with "/S", the particular letter is not important but rather the position in the list. The third to the last switch, "/O", causes FORMAT to produce an IBM Personal Computer DOS version 1.x-compatible disk. Normally FORMAT causes a 0 byte to be placed in the first byte of each directory entry instead of the 0E5H free entry designator. This markedly increases the performance of a directory search due to an optimization in the DOS. Disks made with this switch cause trouble on IBM PC DOS 1.x versions which did not have this optimization. The 0 byte fools IBM 1.x versions into thinking these entries are allocated instead of free. Note that IBM Personal Computer DOS version 2.10 and MS-DOS version 1.25 have no trouble with these disks, since they have the same optimization. The "/O" switch causes FORMAT to redo the directory with a 0E5H byte at the start of each entry so that the disk may be used with 1.x versions of IBM PC DOS, as well as with MS-DOS 1.25/2.XX and IBM PC DOS 2.00/2.10. This switch should only be given when needed because it takes a fair amount of time for FORMAT to perform the conversion, and it noticeably decreases 1.25 and 2.x performance on disks with few directory entries. A "/C" switch is specified for "Clear". This switch should cause the formatting operation to be bypassed (within DISKFORMAT or BADSECTOR). This is provided as a time-saving convenience to the user, who may wish to "start fresh" on a previously formatted and used disk. The "/T:" option is used to specify the number of tracks that Format will place on a floppy disk. The "/N:" option is used to specify the number of sectors per track that Format will use to format a floppy disk. BIOSFILE & DOSFILE The BIOSFILE and DOSFILE data strings are used to specify the filenames for the hidden BIOS and DOS system files written to the formatted disk when the /s option is selected. The filename strings should be null terminated root directory specifications commencing with a dummy non-zero drive letter byte which will be modified by the FORMAT module at run-time. eg. BIOSFILE db "x:\IO.SYS",0 DOSFILE db "x:\MSDOS.SYS",0 The following data is declared PUBLIC in Microsoft's FORMAT module and may be used by the OEM's module as required. SWITCHMAP A WORD value with a bit vector indicating which switches are included in the command line. The correspondence of the bits to the switches is determined by SWITCHLIST. The extreme right (highest-addressed) switch in SWITCHLIST (which must be the system transfer switch, normally "/S") corresponds to bit 0, the second from the right, normally "/V" to bit 1, etc. For example, if SWITCHLIST is the string "7,'AGI2OVS'", and the user specifies "/G/S" on the command line, then bit 6 will be 0 (/A not specified), bit 5 will be 1 (/G specified), bits 4,3,2 and 1 will be 0 (neither I,2,O or V specified), and bit 0 will be 1 (/S specified). FBIGFAT BYTE which takes on one of two possible values, 0 or 0FFH. WARNING: Any value other than 0 or 0FFH will cause FORMAT to do very odd things. The value 0 indicates that the disk being formatted will have a 12-bit FAT. The value 0FFH means that the disk being formatted will have a 16-bit FAT. DRIVE A byte value containing the drive specified in the command line. 0=A, 1=B, etc. DRIVELETTER A byte value containing the ASCII value of the drive letter specified in the command line. DEVICEPARAMETES A structue containing the device parameters of the drive to be formatted. The format of the DEVICEPARAMETERS data structure is as follows; DP_SpecialFunctions : BYTE DP_DeviceType : BYTE DP_DeviceAttributes : WORD DP_Cylinders : WORD DP_MediaType : BYTE DP_BPB : BPB DP_TrackTableEntries : WORD DP_sectorTable : BYTE TABLE INBUFF A string buffer used to return a character string entered from the keyboard in the user_string routine in the FORMAT module. CURRENTHEAD A word value containing the drive head which was being formatted when an error occurred. CURRENTCYLINDER A word value containing the drive cylinder which was being formatted when an error occured. FLASTCHANCE A byte value used to flag whether a format message is to printed at the start of a format attempt. NUMSECTORS A word value containing the number of sectors specified in the command line with the /n switch. TRACKCNT A word value containing the number of sectors specified in the command line with the /t switch. The detailed description of the routines required to be declared public in the OEM's module is as follows; OEMDONE This routine is called after the formatting has been completed, the disk directory has been initialized and the system has been transferred if specified. It is called once for each disk to be formatted. This gives the chance for any finishing up operations, if needed. If the OEM desires extra files to be put on the formatted disk by default, or according to a switch, this could be done in OEMDONE. The OEMDONE routine should also check for the /b switch and, if present, should notify the FORMAT module of a non-standard system size by calling the ADDTOSYSTEMSIZE routine in the FORMAT module. The following data items form the inputs to the OEMDONE routine; SwitchMap : A WORD vaule indicating which switches were selected. The format of the SwitchMap is as described previously. The OEMDONE outputs should be; Carry Flag : Set on error, else clear. If an error status is returned by OEMDONE, the error message "Format failure" and a prompt for another disk will be displayed. WRITEBOOTSECTOR This routine is called once for each disk formatted after the format has occured but prior to installing a system on the disk. The routine writes the OEM specific boot sector(s) to the disk. The first boot sector must be written to the disk with an initialized BPB. The boot code may be contained within the OEMFOR module and copied to the boot sectors by this routine or may be written to the boot sectors after the format using a separate OEM utility as long as the BPB is written in this routine. The functionality of the code and data required in the boot sector(s) is discussed in detail in section 4.4 . If an error occurs while writing the boot sector(s) the routine should display an error message and return with the carry flag set. CHECKSWITCHES This routine is called once before any disks have been formatted. It is used to verify that the switches selected are a legal combination for the drive type to be formatted and to modify the drive device parameters according to the selected switches if they are valid. For example the valid swith combinations for supported drive types could be; Disk Type Valid switches 160/180KB /l /4 /8 /b /n /t /v /s 320/360KB /l /4 /8 /b /n /t /v /s 720KB /n /t /v /s 1.2MB /n /t /v /s Hard disk /v /s The CHECKSWITCH routine is included in the OEMFOR module so that the OEM may decide what action to take for an OEM specific drive type with the switch combination selected. The following data items form the inputs to the CHECKSWITCHES routine; deviceParameters : A data structure containing the drive parameters for the drive to be formatted. The fields of this structure are as descibed previously. SwitchMap : A WORD vaule indicating which switches were selected. The format of the SwitchMap is as described previously. NumSectors : A WORD value containing the number of sectors specified with the /n switch if it was present in the command line. NumTracks : A WORD value containing the number of tracks specified with the /t option if it was present in the command line. The CHECKSWITCHES outputs should be; Carry Flag : Set on error, else clear. deviceParameters : Device parameters to use in the format operation. Should have been modified by CHECKSWITCES if a legal switch combination specifies parameter modification. NumSectors : If the /n switch was not present in the command line then the CHECKSWITCHES routine should initialize the NumSectors WORD from the deviceParamaters structure. Trackcnt : If the /t switch was not present in the command line then the CHECKSWITCHES routine should initialize the Trackcnt WORD from the deviceParamaters structure. LASTCHANCETOSAVEIT This routine is called when an error, other than a write protect or not ready error, occurs during the disk format. It gives the OEM a chance to modify the disk parameters to be used in the format operation. The format will then be tried with these parameters. An example of when this could be used is if the format fails on the second head (track zero), the OEM may want to try formatting the disk single sided. The LASTCHANCETOSAVEIT inputs are: deviceParameters : A data structure containing the drive parameters for the drive being formatted when the error occurred. The fields of this structure are as described previously. currentCylinder : A WORD value indicating the drive cylinder on which the error occurred. currentHead : A WORD value indicating the drive head on which the error occurred. The LASTCHANCETOSAVEIT outputs should are: Carry Flag : Set if the error was fatal and no attempt is to be made to re-format the drive, else clear. deviceParameters : Modified to contain the new parameters for the re-format, if a re-format attempt required. fLastChance : A BYTE value set to TRUE if an attempt to re-format the drive is required. This prevents multiple format messages for a single drive format. The following routines are declared PUBLIC in Microsoft's FORMAT module and may be used by the OEMFOR module as required. ADDTOSYSTEMSIZE Adds to the number of sectors reserved for the system. INPUTS : ax = size of system file in bytes. OUTPUTS : None. PRINTSTRING Displays a character string. INPUTS : dx = near pointer to null terminated string. OUTPUTS : None. STD_PRINTF Displays a character string. INPUTS : dx = near pointer to a near pointer to a null terminated string. OUTPUTS : None. CRLF Outputs a carriage return and linefeed to the console. INPUTS : None. OUTPUTS : None. USER_STRING Get a string from the keyboard. INPUTS : None. OUTPUTS : Zero flag set if only was enterred. String length in BYTE at offset INBUFF + 1. Console input in INBUFF commencing at offset INBUFF +2. Once the OEM-supplied module has been prepared, it must be linked with Microsoft's FORMAT.OBJ module, and the FORMES.OBJ module. In 3.XX, there are additional format modules that must be linked in. If the OEM-supplied module is called OEMFOR.OBJ, then use the following linker command; link format forproc formes oemfor printf; This command produces an executable file called FORMAT.EXE. NOTE: The OEM's module CAN NOT make the assumption, as it could in the previous versions, that it is at the "end" of the memory image. It must use function 48h (allocate memory) if required. 7.3 FORMAT MODULES AND THE ES REGISTER If an OEM-written FORMAT module, such as OEMDONE, makes use of the ES register, the value of ES should be established by the OEM's code. The contents of the ES register cannot be assumed. CONTENTS CHAPTER 7B WRITING THE FORMAT MODULE FOR MS-DOS 2.25/3.10 7.1 Introduction 7-1 7.2 Format Modules and the ES Register 7-9 7.3 Changing the Logical Format of Disks 7-9 CHAPTER 7B WRITING THE FORMAT MODULE MS-DOS 2.25/3.10 HIGHLIGHTS OF CHANGES IN 3.XX OVER PREVIOUS 2.XX FORMAT VERSION: o FORMAT is now designed to be an .EXE file. o The FBIGFAT variable has been introduced for 16-bit FAT support. o ALLOCATEFAT routine allows space for the FAT to be dynamically allocated. 7.1 INTRODUCTION The MS-DOS Format command formats a new disk, clears the FAT and directory, and optionally copies system files and COMMAND.COM to the new disk. Since the Format command must perform functions that have no equivalent in MS-DOS function calls, FORMAT is shipped in two hardware-independent object modules. These must be linked to a hardware-specific module written by the OEM. The following section describes the routines required in this module. A sample OEM format module is included on the MS-DOS release disks to assist in writing these routines. The syntax for the Format command is: Format [drive:][/switch1][/switch2]...[/switch16] "drive:" is a legal drive specification. If it is omitted, the default drive will be used. As many as 16 legal switches can be included in the command line. WRITING THE FORMAT MODULE Page 7-2 In 3.XX the OEM must supply six (NEAR) routines to the program along with seven data items. In 2.XX the OEM must supply five (NEAR) routines to the program along with six data items. The names of the routines are: ALLOCATEFAT INIT DISKFORMAT BADSECTOR WRTFAT DONE ALLOCATEFAT is used only in 3.XX. Their flow of control (by the Microsoft module) is like this: | +-------------+ | ALLOCATEFAT | +-------------+ | +---------+ | INIT | +---------+ | |<------------------------------+ +------------+ | | DISKFORMAT | | +------------+ | |<-------+ | +-----------+ |-This loop is done |- This loop is | BADSECTOR | | for each group of | done once for +-----------+ | bad sectors | each disk to be |----->--+ | formatted. If | | variable HARDFLAG +----------+ | is set then the | | | loop is only | WRTFAT | | performed once. +----------+ | | | +------+ | | DONE | | +------+ | +---->--------------------------+ The ALLOCATEFAT, INIT, DISKFORMAT, and BADSECTOR routines are free to use any MS-DOS system calls, except for calls that cause disk accesses on the disk being formatted. DONE may use any calls, since by the time it is called the new ___ disk has been formatted. WRITING THE FORMAT MODULE Page 7-3 The following data must be declared PUBLIC in a module provided by the OEM: SWITCHLIST A string of bytes. The first byte is count n, followed by n characters that are the switches to be accepted by the command line scanner. Alphabetic characters must be in uppercase (the numeric characters 0-9 are allowed). The last three switches, normally "/O", "/V" and "/S", have pre-defined meanings. The "/S" switch is the switch that causes the system files IO.SYS, MSDOS.SYS, and COMMAND.COM to be transferred to the disk after it is formatted, thus making a system disk. The switch can be some letter other than "S", but the last switch in the list is assumed to have the meaning "transfer system," regardless of what the particular letter is. The second to the last switch, "/V", causes FORMAT to prompt the user for a volume label after the disk is formatted. As with "/S", the particular letter is not important but rather the position in the list. The third to the last switch, "/O", causes FORMAT to produce an IBM Personal Computer DOS version 1.x-compatible disk. Normally FORMAT causes a 0 byte to be placed in the first byte of each directory entry instead of the 0E5H free entry designator. This markedly increases the performance of a directory search due to an optimization in the DOS. Disks made with this switch cause trouble on IBM PC DOS 1.x versions which did not have this optimization. The 0 byte fools IBM 1.x versions into thinking these entries are allocated instead of free. Note that IBM Personal Computer DOS version 2.10 and MS-DOS version 1.25 have no trouble with these disks, since they have the same optimization. The "/O" switch causes FORMAT to redo the directory with a 0E5H byte at the start of each entry so that the disk may be used with 1.x versions of IBM PC DOS, as well as with MS-DOS 1.25/2.XX and IBM PC DOS 2.00/2.10. This switch should only be given when needed because it takes a fair amount of time for WRITING THE FORMAT MODULE Page 7-4 FORMAT to perform the conversion, and it noticeably decreases 1.25 and 2.x performance on disks with few directory entries. Up to 16 switches are permitted. Normally a "/C" switch is specified for "Clear". This switch should cause the formatting operation to be bypassed (within DISKFORMAT or BADSECTOR). This is provided as a time-saving convenience to the user, who may wish to "start fresh" on a previously formatted and used disk. HARDFLAG BYTE location which specifies whether the OEM routine is formatting a fixed disk or a drive with removable media. A zero means removable media; any other value indicates a fixed disk. The status of this byte only affects the messages printed by the main FORMAT module. This value should be set or reset by the OEM-supplied INIT routine. FATID BYTE location containing the value to be used in the first byte of the FAT. Must be in the range F8H to FFH. STARTSECTOR WORD location containing the sector number of the first sector of the data area. FATSPACE WORD location containing the address of the start of the FAT area. A FAT built in this area will be written to disk using the OEM-supplied WRTFAT subroutine. 6K is sufficient to store any 12-bit FAT. This area must not overlap the FREESPACE area. FREESPACE WORD location that contains the address of the start of free memory space. This is where the system will be loaded by the Microsoft module for transferring to the newly formatted disk. Memory should be available from this address to the end of memory, so it is typically the address of the end of the OEM module. WRITING THE FORMAT MODULE Page 7-5 FBIGFAT BYTE which takes on one of two possible values, 0 or 0FFH. WARNING: Any value other than 0 or 0FFH will cause FORMAT to do very odd things. The value 0 indicates that the disk being formatted will have a 12-bit FAT. The value 0FFH means that the disk being formatted will have a 16-bit FAT. See ALLOCATEFAT call, below, for details. FBIGFAT is used only in 3.XX. The following routines must be declared PUBLIC in the OEM-supplied module: ALLOCATEFAT ALLOCATEFAT is used only in 3.XX. It is an initialization routine. This routine is called once at the start of the FORMAT run after the switches have been processed. This routine must set the correct values of FBIGFAT, FATSPACE, and FREESPACE. With only 12-bit FATs it was convenient to allocate a FAT area of 6K (maximum size of a 12-bit FAT) as part of the memory image of FORMAT. With the advent of 16-bit FATs in DOS 3.XX this is no longer convenient; the maximum size of of a FAT is 32K. ALLOCATEFAT is a dynamic space allocator that allocates enough memory to hold the FAT by setting the values of FATSPACE and FREESPACE. ALLOCATEFAT must also set FBIGFAT so that FORMAT knows whether the disk has a 12 or a 16-bit FAT. FBIGFAT must be set consistently with the following FAT rule (see below). The 16-bit FAT rule: - Any disk with less than 4086 clusters has a ____ ____ 12-bit FAT. - Any disk with greater than or equal to 4086 _______ ____ __ _____ __ clusters has a 16-bit FAT. The OEM FORMAT module cannot force a 16-bit FAT if the total number of clusters is less than 4086. Similarly, you cannot have a 12-bit FAT on a disk with more than 4085 clusters. If the OEM module does not set FBIGFAT consistently with the 16-bit FAT rule, the disk will not be formatted correctly, and MS-DOS will not access the disk in the proper manner. WRITING THE FORMAT MODULE Page 7-6 Currently, there is no error return from ALLOCATEFAT. It should exit with CARRY CLEAR, however, so that it is consistent with the other routines. The Microsoft 3.XX FORMAT.OBJ is responsible for checking that the memory needed for the FAT is actually available to the system. It will produce a "Insufficient memory for system transfer" error when memory is inadequate. This error is produced when memory is inadequate for both "/S" and non "/S" procedures. INIT An initialization routine. This routine is called once at the start of the FORMAT run after the switches have been processed. This routine should perform any functions that need to be done once per FORMAT run. An example of what this routine might do is read the boot sector into a buffer so that it can be transferred to the new disks by DISKFORMAT. If this routine returns with the CARRY flag set, it indicates an error, and FORMAT will print "Format failure" and quit. This feature detects conflicting switches (like specifying both single and double density) and causes the FORMAT routine to abort. DISKFORMAT Formats the disk according to the options indicated by the switches and the value of FATID must be defined when it returns (although INIT may have already done it). This routine is called once for each disk to be formatted. If necessary, it must transfer the bootstrap loader. If any error conditions are detected, the carry flag is set. FORMAT will report a "Format failure" and prompt for another disk. (If you only require a clear directory and FAT, all that DISKFORMAT must do is set the appropriate FATID, if this has not already been done by INIT. BADSECTOR Reports the sector number of any bad sectors that may have been found during the formatting of the disk. This routine is called at least once for each disk to be formatted, and is called repeatedly until the AX register is zero or the carry flag is set. The carry flag is used just as in DISKFORMAT to indicate an error, and FORMAT handles it in the same way. The first sector in the data area must be in STARTSECTOR for the returns from this routine to be interpreted correctly. If there are bad sectors, BADSECTOR must return a sector number in WRITING THE FORMAT MODULE Page 7-7 register BX, the number of consecutive bad sectors in register AX, and clear the carry flag. FORMAT will then process the bad sectors and call BADSECTOR again. When BADSECTOR returns with AX = 0, there are no more bad sectors; FORMAT clears the directory and goes on to DONE. For this last return, BX need not contain anything meaningful. FORMAT processes bad sectors by determining their corresponding allocation unit and marking that unit with an FF7H in the File Allocation Table. CHKDSK understands the FF7H mark as a flag for bad sectors and accordingly reports the number of bytes marked in this way. Actual formatting of the disk can be done in BADSECTOR instead of DISKFORMAT on a "report as you go" basis. Formatting continues until a group of bad sectors is encountered; BADSECTOR then reports them by returning with AX and BX set. FORMAT will then call BADSECTOR again and formatting can continue. WRTFAT This routine is called after the disk is formatted and bad sectors have been reported. It writes all copies of the FAT from the area of memory referenced by FATSPACE to the drive just formatted. It may be possible to use INT 26H to perform the write, or a direct BIOS call. Whether this is possible depends on whether the FAT ID byte is used by the BIOS to determine the media in the drive. If it is, these methods will probably fail because there is no FATID byte on the disk yet (in this case WRTFAT's primary job is to get the FATID byte out on the disk). DONE This routine is called after the formatting has been completed, the disk directory has been initialized, and the system has been transferred if specified. It is called once for each disk to be formatted. This gives the chance for any finishing-up operations, if needed. If the OEM desires extra files to be put on the disk by default, or according to a switch, this could be done in DONE. WRITING THE FORMAT MODULE Page 7-8 Again, as in BADSECTOR and DISKFORMAT, carry flag set on return means an error has occurred; "Format failure" will be printed and FORMAT will prompt for another disk. The following data is declared PUBLIC in Microsoft's FORMAT module: SWITCHMAP A WORD value with a bit vector indicating which switches are included in the command line. The correspondence of the bits to the switches is determined by SWITCHLIST. The extreme right (highest-addressed) switch in SWITCHLIST (which must be the system transfer switch, normally "/S") corresponds to bit 0, the second from the right, normally "/V" to bit 1, etc. For example, if SWITCHLIST is the string "7,'AGI2OVS'", and the user specifies "/G/S" on the command line, then bit 6 will be 0 (/A not specified), bit 5 will be 1 (/G specified), bits 4,3,2 and 1 will be 0 (neither I,2,O or V specified), and bit 0 will be 1 (/S specified). Bits 0,1 and 2 are the only switches used in Microsoft's FORMAT module. These switches are used 1) after INIT has been called to determine if it must load the system; 2) after the last BADSECTOR call to determine if the system should be written, E5 directory conversion should be done, and/or a volume label should be asked for. INIT may force these bits set or reset if desired (for example, some drives may never be used as system disk, such as hard disks). After INIT, the "/S" bit may be turned off (but not on, since the system was never read) if something happens that means the system should not be transferred. After INIT, a second copy of SWITCHMAP is made internally.It is used to restore SWITCHMAP for each disk to be formatted. FORMAT will turn off the system bit if bad sectors are reported in the system area; DISKFORMAT and BADSECTOR are also allowed to change the map. However, these changes affect only the current disk being formatted, since SWITCHMAP is restored after each disk. (Changes made to SWITCHMAP by INIT affect all disks.) WRITING THE FORMAT MODULE Page 7-9 DRIVE A byte value containing the drive specified in the command line. 0=A, 1=B, etc. Once the OEM-supplied module has been prepared, it must linked with Microsoft's FORMAT.OBJ module, and the FORMES.OBJ module. In 3.XX, there are additional format that must be linked in. If the OEM-supplied module is called OEMFOR.OBJ, then use the appropriate linker command. 2.XX LINK FORMAT.OBJ+FORMES.OBJ+OEMFOR.OBJ 3.XX LINK FORMAT.OBJ+FORPROC.OBJ+FORMES.OBJ+OEMFOR.OBJ.PRINTF.OBJ For 3.XX, the command produces an executable file called FORMAT.EXE. Note that although the PRINTF.OBJ module is the last module specified, it does not follow the OEMFOR module in the memory image. The OEMFOR module can still make the assumption, as it has in the past, that it is at the "end" of the memory image. For 2.XX, the command produces a FORMAT.EXE file which must be changed to a simple binary. This should be done with the following command. EXE2BIN FORMAT.EXE FORMAT.COM This produces the 2.XX file, FORMAT.COM. 7.2 FORMAT MODULES AND THE ES REGISTER If an OEM-written FORMAT module makes use of the ES register, such as DISKFORMAT, the value of ES should be established by the OEM's code. The contents of the ES register cannot be assumed. WRITING THE FORMAT MODULE PAGE 7-10 7.3 CHANGING THE LOGICAL FORMAT OF DISKS MS-DOS has an internal table which it builds from information returned by the BIOS BUILDBPB routine. There is a table maintained for each drive within the system and it is updated to reflect the media type whenever a new disk is loaded. Before any access to the disk directory, MS-DOS calls the BIOS MEDIACHECK routine. If a disk change is reported, MS-DOS calls the BIOS BUILDBPB routine to get the new media information and updates its internal table. It is important to realize that MS-DOS operates with its own table and not with any table within the BIOS. FORMAT can be used to physically reformat the disk from single to double-sided use. Therefore, the WRTFAT routine should ensure that the next call to the BIOS MEDIA CHECK/BUILD BPB routines made by the DOS will set the media type to the type just formatted. This is because when the format operation is started, the DPB (Drive Parameter Block) reflects the media that existed before the format. This may need to be changed because the disk media may have been changed due to the format process. Since this is basically a communication between the OEM part of the FORMAT utility and the OEM BIOS, it is up to the OEM to determine the most efficient and appropriate way to determine the correct media type. As an example, the FORMAT utility can call the BIOS and cause the BIOS to return "media changed" on the next MEDIA CHECK call made by the DOS. The DOS will then call the BUILDBPB BIOS routine; it must return the correct BPB for the disk just formatted. Trying to determine media change externally with the FORMAT utility calling the DOS will not work. You must: o Have the correct BPB in the BIOS, and your FORMAT utility must communicate that information down to your BIOS, or o Your BIOS must detect that the disk has been changed when the FORMAT utility is used. Then, the BIOS can look on the disk for the BPB and tell the DOS what the new BPB is. The OEM may decide how this can be structured. The BIOS can be in control and inform FORMAT what was done, or FORMAT can be in control and inform the BIOS that the media has changed. There is an example of an OEM written FORMAT module on the Sample MS-DOS Implementation Diskette. CONTENTS CHAPTER 8 TROUBLE-SHOOTING CHAPTER 8 TROUBLE-SHOOTING The following section addresses typical problems that you may encounter when installing MS-DOS. Problem: When I type "r" for Retry when a disk error occurs, the system crashes. Typical Cause: When an error occurs during I/O, your device driver must report the number of sectors or characters correctly transferred. If you just set the error bit, MS-DOS will assume that it was able to read all of the sectors since the sector count will be the same as that set by MS-DOS. Recommendation: Report the actual number of sectors/bytes transferred in addition to reporting the error. Problem: I am booting up MS-DOS. I see the MS-DOS copyright message on the screen, but then I get the message "Bad or missing command interpreter." Typical Cause: SYSINIT is executing COMMAND.COM. This is the conclusion of MS-DOS initialization and is the first time that the disk must be read successfully. (Failure to find CONFIG.SYS is not an error.) Either COMMAND.COM is not on the disk or an invalid Bios Parameter Block (BPB) has been returned to MS-DOS so it does not correctly understand the format of the disk. TROUBLE-SHOOTING Page 8-2 Recommendation: Check that the correct BPB is being returned and that COMMAND.COM is on disk. Install debugging code in the device driver to make sure requests to the device driver make sense. Problem: I am booting up MS-DOS. I get the MS-DOS copyright message on the screen, but then I get the message "Bad or missing /DEV/CON." Typical Cause: SYSINIT has closed all file handles and is now reopening them. The first file it opens is /DEV/CON, which is your console device. The system file table is examined for this device. /DEV/CON should be present. If it is not found, some of your IO.SYS code has destroyed the system file table or MS-DOS itself. This may happen if you have blown the MS-DOS stack, causing MS-DOS to write over the file table. Recommendation: Use a local stack in your device drivers. Problem: MS-DOS is trying to read some sectors starting at an extremely large or invalid sector number. Typical Cause: The BPB that you returned for the drive is bad. Recommendation: The INIT and BUILD BPB device driver routines should be checked. Problem: After I jump to SYSINIT, control never comes back. Typical Cause 1: You may not have loaded MS-DOS correctly with your bootstrap loader. SYSINIT must know exactly where MS-DOS is. MS-DOS must be on a paragraph boundary and CURRENT_DOS_LOCATION and FINAL_DOS_LOCATION must be set up accordingly. TROUBLE-SHOOTING Page 8-3 Recommendation: Check the location of MSDOS.SYS after bootstrap loading. Typical Cause 2: You are incorrectly reporting the amount of memory in the system or the memory scan is failing because of a discontinuity. Recommendation: Don't move MS-DOS after bootstrap loading. Don't request a memory scan. Make sure memory is contiguous. Typical Cause 3: MS-DOS can't find the beginning of the device list. Recommendation: Check the value passed to SYSINIT to make sure that it is the correct value for the beginning of the list. Typical Cause 4: The driver attributes are wrong. MS-DOS will not look for the end of list mark if the attributes are wrong. Recommendation: Check the device driver attribute words. Typical Cause 5: You do not have a driver in the linked list of device drivers with the CLOCK attribute bit set. This is necessary before SYSINIT will start looking for FFFF, FFFF in the last device driver. Recommendation: Be sure you have a CLOCK device in your linked list with its attribute word set properly. Problem: Everything was working great, but when I tried to install a new device, the system wouldn't boot. Typical Cause: You are failing to set the BREAK ADDRESS during the TROUBLE-SHOOTING Page 8-4 device INIT routine. This points to the first byte of free memory after the device code and data. Recommendation: Set the break address. Problem: Everything works OK until I define a new drive in IO.SYS. Then the system won't come up. Typical Cause: You are returning invalid data from the INIT call to the block device driver. Recommendation: Examine the INIT call. This is probably not being handled correctly. You should return a DWORD pointer to an array of WORD POINTERS to BPBs. The array must be below the 'break address' returned by INIT. There should be one array element for each drive defined. The number of subunits is also returned by the INIT call. Problem: My device driver defines two drives, but when I try to use drive B, I get an "Invalid drive specification" message. Typical Cause: You are not handling the INIT call to the device driver properly. Recommendation: The INIT call should return the value "2" at offset 13 from the beginning of the static request header. Problem: When I have a single-sided disk in drive B and remove it and install a double-sided disk, MS-DOS treats the double-sided disk like a single-sided disk. I am returning the correct BPB for the double-sided disk. Typical Cause: The media bytes in the BPBs are not unique. Recommendation: TROUBLE-SHOOTING Page 8-5 Each BPB has a unique media byte. MS-DOS will not rebuild its internal DPB structure if the media byte doesn't change. Problem: I have a one-drive system. When I type B:, I get an "Invalid drive specification" message, but on some single-drive machines, MS-DOS prompts me for the "disk for drive B:." Typical Cause: The INIT call is only defining one disk drive and support for swapping has not been implemented in IO.SYS. Recommendation: Support for disk swapping is implemented at the IO.SYS file level rather than at the MS-DOS level. The driver reports two drives and when it sees a request for unit 1 (the second drive), it prints the swap message directly on the screen. Problem: Everything is running fine, but when I run Chkdsk I find that I only have 60K bytes free, but I have a 128K machine. I know that DOS and IO.SYS only take up 24K. What is happening to the missing bytes? Typical Cause: The Block Device Driver INIT call is returning a bad BPB pointer which reports an absurdly large sector size. This sector size is used to make all of the sector buffers, and consequently wastes thousands of bytes. You could have incorrectly set FINAL_DOS_LOCATION or installed a device driver that returned an 'absurdly large' break address. Recommendation: Fix the block device driver INIT call. Problem: Every time I try to do an Allocate Memory call (Function 48H) or an EXEC call, I get a return code of 8, "Not enough memory." Typical Cause: There is no free memory. TROUBLE-SHOOTING Page 8-6 Recommendation: Do a Set Block (Function 4AH) call to shrink the size of the currently allocated block, freeing some memory. See the section on arenas in the Glossary. Problem: When running a program that opens a number of files via Function Request 3DH, the file open fails even though the file is present on the disk. Typical Cause: You have run out of entries in the system file table. Recommendation: Increase the "FILES = " entry in CONFIG.SYS and reboot. Problem: Control-S, Control-P, and the other control characters seem to be ignored by MS-DOS. Typical Cause: The non-destructive console read routine is not implemented properly. Recommendation: Check the non-destructive read routine in the console or other character driver where this problem is occurring. Problem: Sometimes when I am typing a long file to the screen and press Control-S, the Control-S is ignored and doesn't stop the scrolling of the file. I have the same problem with Control-C. Typical Cause: Another character has been typed into the type-ahead buffer first, and the nondestructive read keyboard status check never sees the Control-S or the Control-C. Recommendation: Implement Scroll Lock and Break keys which flush the TROUBLE-SHOOTING Page 8-7 input queue and put the Control-S/Control-C at the beginning of the type-ahead buffer. Problem: I am trying to use EXE2BIN to convert IO.EXE to IO.SYS. I get the message "File cannot be converted." Typical Cause: You have a "SEGMENT AT NNNN" statement and there is code or initialized data in that segment. You may also have a stack segment, which is not permitted. Recommendation: Remove the "SEGMENT AT" statement or remove code or initialized data from the segment. It is possible, if your code contains FAR references, that EXE2BIN may request a 'Fixup' address. If your IO.SYS will always be loaded at the same place in memory, this may be OK. Check your FAR references in any case. APPENDIX A CUSTOMIZATION OF MS-DOS AND INTERNATIONALIZATION A.1 CUSTOMIZING MS-DOS Many manufacturers find it necessary to customize MS-DOS (as distinct from IO.SYS) to some degree. The function key table and OEM serial number are often modified. The function key table is found in the DOSMES.ASM file. Extensive modification to this table may require modifying the line input routines in STRIN.ASM, which is available to source licensees only. OEM Serial Numbers: Each OEM is eligible for a unique OEM Serial Number. The Series is 0 to FF (255). IBM is 00 and we are currently at about 50H on list. These numbers are assigned sequentially by MS-DOS Product Marketing as requested through the OEM's Account Manager. Once the OEM has this number they can modify the default FF value in the file DOSMES.ASM that is part of the adaptation kit. If this is done, when MSDOS.SYS file is built it will the right value. It can be patched after they MSDOS.SYS is built by following the instructions in the README.DOC on the MS-DOS DISTRIBUTION DISKETTES. Function Request 30H - Get MS-DOS Version Number will return the version of the DOS that is being run, the OEM Serial number and the OEM user number. To implement OEM user number concept properly each individual disk shipped should have to have a separate user number patched in according to the directions in the README.DOC on the MS-DOS DISTRIBUTION DISKETTES. The OEM serial number can, however, be used without using the OEM User Number. With these numbers properly installed, an application program could tell which version of MS-DOS was being run, which OEM had sold it and which customer had bought it. Internationalization may also require customizing MS-DOS. The file named DOSMES.ASM contains a case conversion routine and a table used to translate foreign characters into their uppercase equivalents. This routine defaults to no case conversion, and a sample for the IBM PC character set is included. Note that this table is country-dependent. You should not translate a lowercase character available on the keyboard into a uppercase equivalent that is not on the ___ keyboard. For example, in France, translate lowercase c cedilla into uppercase C (not C cedilla); in Germany, translate lowercase "a umlaut" into uppercase A umlaut. DOSMES.ASM also contains country-dependent tables used by the international system call (Function 38H). MS-DOS utilities and COMMAND.COM make two system calls to determine time and date formats and the location of the case conversion routine. You may supply as many tables as you wish; however, it is not necessary to supply tables for all countries in all translations. You should include tables for all countries into which a language translation is distributed. For example, French might include tables for France, Belgium, and Switzerland. All versions should include a U.S. table as well. There is a pointer in DOSMES.ASM to the table to which MS-DOS should default if the user specifies no "COUNTRY =" parameter in CONFIG.SYS. Country numbers follow the information telephone codes where two-digit numbers are employed. CUSTOMIZATION OF MS-DOS AND INTERNATIONALIZATION Page A-2 A non-ASCII character text is represented by variables equated at the beginning of the file. These default to the IBM PC character set. If your character set is different, redefine the equates and reassemble, linking the message file with the code files. The SORTMES.ASM file contains a table for collating sequences. This defaults to no mapping; all uppercase ASCII is sorted before all lowercase ASCII. A sample table for the IBM PC character set is included. Note that there is no capability for equating a single character to a multiple character string or vice versa. Therefore, German implementations cannot equate an umlaut to "ae", but may choose to equate it to "a" or have it fall between "a" and "b". A.2 EXTENDED CHARACTER SET (ECS) CONSIDERATIONS - MS-DOS 2.25 All ECS characters are two-byte quantities which also display as two physical character positions (double-written) on the screen and printer. This imposes some constraints on the IO.SYS keyboard and screen drivers. MS-DOS ensures that 16-bit ECS characters are treated as a single logical character from the user's standpoint, rather than being confused for two characters. CUSTOMIZATION OF MS-DOS AND INTERNATIONALIZATION Page A-3 A.3 INPUT On input, it is the responsibility of IO.SYS to pass ECS characters to MS-DOS. IO.SYS must handle all Kata-kana-to-ECS conversion or any other method used to enter ECS. IO.SYS always places both bytes of the ECS character into its buffer at once; however, they are passed to MS-DOS as if they are two separate single-byte characters. Therefore, even non-interrupt-driven keyboards should always have the second byte of the ECS character waiting by the time the first byte is accepted by MS-DOS. IO.SYS should never pass an invalid ECS sequence to MS-DOS. A.4 OUTPUT On output, IO.SYS must identify the first byte of an ECS character, set a flag, and wait for the second byte. Once the entire ECS character has been received, IO.SYS indexes into the font table. The font table may be in memory, on disk, or in a combined memory-disk caching scheme. IO.SYS may call MS-DOS to read font files stored on the disk in MS-DOS format. These files should be opened in IO.SYS when control is passed back to RE_INIT, after MS-DOS has been initialized. IO.SYS performs error recovery in case the font files are on a disk that has been removed. Door lock detection is most helpful here. Files should be reopened whenever the potential for a changed disk occurs. MS-DOS screen and keyboard routines are not reentrant, and cannot be called from within IO.SYS to facilitate recovery from this error. A solution to the problem of missing font files is to display all ECS characters for which no font is in memory as double-width reverse video blanks. IO.SYS also must perform error handling in the data stream where an invalid ECS sequence is sent. Although invalid characters should never be input from the keyboard, they can be output by several occurrences: 1. The user can display a garbage file, such as a binary executable file. 2. A program may have executed a file with bad ECS data. 3. The manipulation of fixed length fields may have split a ECS character between its two bytes. CUSTOMIZATION OF MS-DOS AND INTERNATIONALIZATION Page A-4 If any of these occur, the recommended procedure is to display a double-width reverse video blank character followed by the single-byte ASCII value for the character outside of the valid second-byte range. This will help to resynchronize the data stream as soon as possible. MS-DOS recognizes double-byte values, such as blank space, over ECS in its line editing procedures. It also will accept and display (if appropriate) the second byte where a single-byte response is anticipated ("Strike any key"). IO.SYS should ensure that a ECS character is never split across the last column of one physical line and the first column of the next line. The entire ECS character must start on the next line. IO.SYS must keep a flag for each line to determine whether one or two logical backspace operations should be performed. The "Backspace-Space- Backspace" destructive operation issued by MS-DOS will work properly. For example, starting with column 1, assume that text runs up to and includes column 79. MS-DOS requests that a double-byte ECS character be displayed. IO.SYS: 1. Blanks column 80. 2. Sets a flag for that physical line. 3. Moves to the beginning of the next line. 4. Displays both bytes. MS-DOS requests two backspaces over this ECS character. If a third backspace is issued, IO.SYS must clear the flag and perform an extra backspace, returning to column 79 instead of 80. If a space is issued, column 79 will be blanked. Remember that column 80 was originally blank, so there is no need to reset it. If the ANSI screen driver is also implemented, the driver should never allow only one-half of a ECS character to be block transferred without blanking it in scrolling regions. This rule also applies to both the region being moved and the area into which it is being moved. APPENDIX B HOW TO UPGRADE A 2.XX BIOS TO 3.XX MS-DOS 3.XX provides very few new services that impact device drivers. The basic BIOS mechanisms are identical to those in MS-DOS 2.XX. The only changes are that a few new device driver calls have been added. These calls are not required. ___ There are new device attribute bits that indicate the presence of these new functions. Old device drivers do not have these bits set, and thus indicate that the functions are not present. There are several new CONFIG.SYS commands. The code for these is contained in the SYSINIT modules, and there are no new PUBLICs in SYSINIT, or expected EXTERNs in the BIOS. First, to quickly bring up MS-DOS 3.XX with a 2.XX set of device drivers, all that you need to do is build a new BIOS with the new 3.XX SYSINIT and SYSIMES modules in the same way that the 2.XX BIOS was built. This will produce a perfectly functional BIOS, but none of the devices will have any of the new 3.XX functions implemented. Since you have not modified your BIOS, you cannot support the following features: 1. The IOCTL is Changeable (Function 4408H) call. This is useful for FORMAT and other programs that want to prompt for a change of media. 2. The character device OPEN and CLOSE device driver calls. These are useful for flushing interrupt-driven I/O. 3. The background print utility spooling to a network printer. 4. Output-until-busy device driver call for PRINT/PSPRINT spool devices. HOW TO UPGRADE A 2.XX BIOS TO 3.XX Page B-2 1. IOCTL Is Changeable Call The IOCTL Is Changeable (Function 4408H) call is fairly easy to implement. Set the appropriate bit in the device-attribute word for your block device drivers, and add the necessary code to return the particular value for your floppies and hard disks. 2. OPEN and CLOSE calls OPEN and CLOSE device driver calls are needed only ____ if you have interrupt-driven I/O. If you omitted this feature, then you have nothing to do. If you support interrupt-driven I/O, set the appropriate bit in the attribute word for your character device driver and add the necessary code to wait until your buffers are empty. ____________________________________________________________ | | | Note | | | | The same bit in the attribute word is used to indicate | | that Is-Removable and OPEN/CLOSE is present. This | | means that you must put in NO-OP stubs for those | | functions you will not use (simply return with no error | | for OPEN/CLOSE). MS-DOS assumes that all three of | | these new functions exist if this attribute bit is set. | | | |__________________________________________________________| 3. Background Print Utility The third feature (background print spooling to a network printer) is difficult to implement. You MAY need to add code to the output loop of the character device driver that tells the network portion of MS-DOS that you sent a character to a particular device. You will also need to modify the code in NETPS (part of the Redirector) to receive this input. The skeleton code in NETPS is for INT 17H (output-to-printer) on the IBM PC. So there is NO SPECIAL CODE in the IBM PC printer device drivers as everything is handled by INT 17H. Your architecture may require a different mechanism. You may wish to use the INT 2FH mechanism to achieve this. If your architecture doesn't provide for Redirection at the ROM BIOS entry level (INT 17H on the IBM PC), your added code in the device driver will signal the network piece that you have a character destined for a particular device. The network piece will decide whether or not that output should be routed across the network. If so, it will handle the character and return an indication that the character was handled. Otherwise, it will indicate that the device driver should take care of HOW TO UPGRADE A 2.XX BIOS TO 3.XX Page B-3 it. After this call in the device driver, the code should examine the return to see if the device driver should process the character or return. The code required to do this is quite small, typically less than 100 bytes. There is more information about how this is done in the Redirector Adaptation Guide that is available on the MS-NET distribution diskette. 4. Output-Until-Busy Call The fourth feature is a new device call that helps the performance of the PRINT and PSPRINT (networking print) utilities. Most printers have RAM buffers which typically hold a line of characters or some fixed amount of characters. These buffers fill up without the printer going busy. This yields a "burst" type of behavior. A line of characters can be very quickly output to the printer, then the printer goes busy for a long time while the characters are being printed. This new device call allows the background spooling programs PRINT and PSPRINT to use this burst behavior efficiently. Rather than take the overhead of a device driver call for each character, or risk getting "stuck" in the device driver outputting a block of characters, this call allows a burst of characters to be output without getting stuck in the device driver waiting for the device to come ready. APPENDIX C HOW TO UPGRADE A 3.10 BIOS TO 3.20 The major change in the MS-DOS 3.2 BIOS is in the device drivers. The device drivers provide the support for the new Generic IOCTL requests. If some of the new MS-DOS 3.2 features are going to be used, then the Generic IOCTL functions have to implemented in the device drivers. For example, the new MS-DOS 3.2 FORMAT utility has been designed to be hardware independent and uses Generic IOCTL's extensively. If the Generic IOCTL's are implemented in the device drivers, then the OEM will not have to modify the FORMAT utility. Refer to the MS-DOS 3.2 Device Drivers Guide and the MS-DOS 3.2 Technical Guide for a complete listing of the use of Generic IOCTL's. NOTE: Old device drivers will still work under MS-DOS 3.2 without the Generic IOCTL's, but will not get the benefit of this feature. The MS-DOS 3.2 BIOS makes use of a new data structure called the Block Data Structure (BDS). The BDS is listed in the file MSBDS.ASM in the sample BIOS disk. This data structure describes the characteristics of a physical block device. The BDS is filled in at BIOS initialization time. The physical characteristics within the BDS can be changed after initialization time by using the DRVPARM option in the CONFIG.SYS file. Any block device drivers that have the special MS-DOS 3.2 version bit set in the attribute word must contain a BDS. The BDS in the device driver will be linked with the other BDS's of the system at initialization time. The BDS structure must be used if the Generic Device Driver (DRIVER.SYS) is to used in the OEM's system. The MS-DOS 3.2 BIOS has extended the concept of logical drives. There can now be more than one logical drive associated with each physical drive. This logical drive mapping is achieved by using the Generic Device Driver, DRIVER.SYS. The extension of logical drives has prompted the idea of "Present Physical Drive Owner". The Present Physical Drive Owner is the last logical drive to have accessed a physical drive. This is an important concept because when a reference is made to a logical drive that is NOT the Present Physical Drive Owner, the BIOS displays the following message: Insert diskette for drive d: and strike any key when ready where d: is the logical drive that was referenced. The Present Physical Drive Owner is stored in the BDS for the particular physical drive. Two new IOCTL calls have been introduced in connection with logical drives. The new calls are GET/SET LOGICAL DRIVE MAP. These two IOCTL's are important for applications that want to control the printing of the message to swap disks. The message to swap disks will only be displayed if the Present Physical Drive Owner is not the same as the logical drive being referenced. Applications that want to control the printing of this message (for example, full screen applications that want to display the swap disk message in a dialogue box) would use these calls to get and set the Present Physical Drive Owner. APPENDIX D This material was taken from the MS-DOS 3.20 Programmer's Reference Manual. It is intended be used with the MS-DOS 2.XX/3.XX Adaptation Guide. CHAPTER 2 MS-DOS DEVICE DRIVERS 2.1 INTRODUCTION The IO.SYS file is composed of the "resident" device drivers, and forms the MS-DOS BIOS. MS-DOS calls upon these resident drivers to handle I/O requests initiated by application programs. One of the most powerful features of MS-DOS is that it lets you add new devices such as printers, plotters, or mouse input devices without rewriting the BIOS. The MS-DOS BIOS is "configurable;" that is, you can add and preempt new drivers and existing drivers. You can also add non-resident device drivers at boot time by using the "DEVICE =" entry in the CONFIG.SYS file. In this section, these non-resident drivers are referred to as "installable" to distinguish them from drivers which, in the IO.SYS file, are considered as the resident drivers. At boot time, a minimum of five resident device drivers must be present. These drivers are in a linked list. The "header" of each driver contains a DWORD pointer to the next. The last driver in the chain has an end-of-list marker of -1, -1 (all bits on). Each driver in the chain has two entry points--the strategy entry point and the interrupt entry point. MS-DOS does not take advantage of the two entry points. Instead, it first calls the strategy routine, then immediately calls the interrupt routine. The dual entry points are provided for future multitasking versions of MS-DOS. In multitasking environments, I/O must be asynchronous; to accomplish this, the strategy routine will be called to (internally) queue a request and return quickly. It is then the responsibility of the interrupt routine to perform the I/O at interrupt time by getting requests from the internal queue and processing them. When a request is completed, the interrupt routine flags it as "done." MS-DOS periodically scans the list of requests, looking for those requests with done flags, and "wakes up" MS-DOS DEVICE DRIVERS Page 2-2 the process that is waiting for the completion of the request. When requests are queued in this manner, it is no longer sufficient to pass I/O information in registers, since many requests may be pending at any one time. Therefore, the MS-DOS device interface uses "packets" to pass request information. These request packets vary in size and format and are composed of two parts: 1. The static request header section, which has the same format for all requests. 2. A section that has information specific to the type of request. A driver is called with a pointer to a packet. In multitasking versions, this packet will be linked into a global chain of all pending I/O requests maintained by MS-DOS. MS-DOS does not implement a global or local queue. Only one request is pending at any one time. The strategy routine must store the address of the packet at a fixed location, and the interrupt routine, which is called immediately after the strategy routine, should process the packet by completing the request and returning. MS-DOS assumes that the request is complete when the interrupt routine returns. To make a device driver that SYSINIT can install, you must create a .BIN (core image) or .EXE format file that contains the device driver header at the beginning of the file. The link field should be initialized to -1 (SYSINIT fills it in). Device drivers that are part of the BIOS should have their headers point to the next device in the list and the last header should be initialized to -1,-1. The BIOS must be a .BIN (core image) format file. If you have a non-IBM compatible version of MS-DOS 2.x, you can use installable device drivers that are in .EXE format. On the IBM PC (or compatible) DOS 2.x versions, the .EXE loader is located in COMMAND.COM, which is not present at the time that MS-DOS is loading the installable devices. 2.2 FORMAT OF A DEVICE DRIVER A device driver is a program segment responsible for communication between DOS and the system hardware. It has a special header at the beginning identifying it as a device driver, defining its entry points, and describing its various attributes. MS-DOS DEVICE DRIVERS Page 2-3 ------------------------------------------------------------ | | | Note | | | | For device drivers, the file must not use the ORG 100H | | (like .COM files). Because it does not use the Program | | Segment Prefix, the device driver is simply loaded; | | therefore, the file must have an origin of zero (ORG 0 | | or no ORG statement). | | | |__________________________________________________________| There are two kinds of device drivers: 1. Character device drivers 2. Block device drivers Character devices perform serial character I/O. Examples are the console, communications port, and printer. These devices have specific names (i.e., CON, AUX, CLOCK, etc.), and programs may open channels (handles or FCBs) to send I/O to them. Block devices are the "disk drives" on the system. They can perform random I/O in structured pieces called blocks (usually the physical sector size). These devices are not named as the character devices are, and therefore cannot be opened directly. Instead they have unit numbers and are identified by drive letters such as A, B, and C. A single block device driver may be responsible for one or more logically contiguous disk drives. For example, the block device driver ALPHA may be responsible for drives A, B, C, and D. This means that it has four units defined (0-3). The position of the driver in the list of all drivers determines which units correspond to which drive letters. For example, if driver ALPHA is the first block driver in the device list, 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. The theoretical limit is 63, but the device installation code does not allow the installation of a device if it would result in a drive letter >`Z' (5AH). All block device drivers present in the standard resident BIOS are placed ahead of installable block-device drivers in the list. MS-DOS DEVICE DRIVERS Page 2-4 ------------------------------------------------------------ | | | Note | | | | Character devices cannot define multiple units | | because they have only one name. | | | |__________________________________________________________| 2.3 HOW TO CREATE A DEVICE DRIVER To create a device driver that MS-DOS can install, you must create a binary file (.COM or .EXE format) with a device header at its beginning. Device driver code should not originate at 100H, but at 0. The device header contains a link field (pointer to next device header) which should be -1, unless there is more than one device driver in the file. You must also correctly set the attribute field and entry points. The name field for a character device should contain the name of that device. This name can be any legal 8-character filename. But if it is less than eight characters, you should pad it out to eight by typing spaces (20H). Note that device names do not include colons (:). The fact that "CON" is the same as "CON:" is a property of the default MS-DOS command interpreter (COMMAND.COM) and not of the device driver or MS-DOS interface. All character device names are handled in this way. MS-DOS always processes installable device drivers before handling the default devices, so to install a new CON device, simply name the device "CON". Remember to set the standard input and standard output device bits in the attribute word on a new CON device. The scan of the device list stops on the first match, so the installable device driver takes precedence. It is not possible to replace the "resident" disk block device driver with an installable device driver as you would replace other device drivers in the BIOS. Block drivers can be used only for devices not supported directly by the default disk drivers in IO.SYS. ------------------------------------------------------------ | | | Note | | | | Because MS-DOS can install the driver anywhere in | | memory, you must be careful when making far memory | | references. You should not expect that your driver | | will always be loaded in the same place every time. | | | |__________________________________________________________| MS-DOS DEVICE DRIVERS Page 2-5 2.3.1 Device Strategy Routine This routine, which MS-DOS calls for each device driver service request, is primarily responsible for queuing these requests in the order in which they are to be processed by the Device Interrupt Routine. Such queuing can be an important performance feature in a multitasking environment, or where asynchronous I/O is supported. Since MS-DOS does not currently support these facilities, only one request (usually a short one) can be serviced at a time. In the coding examples in Section 2.12, each request is simply stored in a single pointer area. 2.3.2 Device Interrupt Routine This routine contains the code necessary for processing the service request. It may interface to the hardware, or it may use ROM BIOS calls. It usually consists of a series of procedures, which handle the specific command codes to be supported, as well as some exit and error-handling routines. See the coding examples in Section 2.12. 2.4 INSTALLATION OF DEVICE DRIVERS MS-DOS allows new device drivers to be installed dynamically at boot time. This is accomplished by IO.SYS initialization code which reads and processes the CONFIG.SYS file. MS-DOS calls upon the device drivers to perform their functions in the following manner: 1. MS-DOS makes a far call to strategy entry. 2. MS-DOS passes device driver information in a request header to the strategy routine. 3. MS-DOS then makes a far call to the interrupt entry. This structure can be easily upgraded to support any future multitasking environment. MS-DOS DEVICE DRIVERS Page 2-6 2.5 DEVICE HEADERS A device header, which is required at the beginning of every device driver, looks like this: +--------------------------------------+ | DWORD Pointer to next device | | (Usually set to -1 if this driver | | is the last or only driver in the | | file) | +--------------------------------------+ | WORD Attributes | +--------------------------------------+ | 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. | +--------------------------------------+ Figure 2.1. Sample Device Header Note that the device entry points are words. They must be offsets from the same segment number used to point to this table. For example, if XXX:YYY points to the start of this table, then XXX:strategy and XXX:interrupt are the entry points. The device header fields are described in the following section. 2.5.1 Pointer to Next Device Field This pointer is a double word field (offset followed by segment). MS-DOS sets this field so that it points to the next driver in the system list at the time the device driver is loaded. Unless there is more than one device driver in the file, it is important that you set this field to -1 prior to loading (when it is on the disk as a file). If there is more than one driver in the file, the first word of the double word pointer should be the offset of the next driver's device header. MS-DOS DEVICE DRIVERS Page 2-7 ------------------------------------------------------------ | | | Note | | | | If there is more than one device driver in the | | file, the last driver in the file must have the pointer | | to the next device header field set to -1. | | | |__________________________________________________________| 2.5.2 Attribute Field The attribute field identifies the type of device this driver is responsible for. In addition to distinguishing between block and character devices, these bits give selected character devices special treatment. (Note that if a bit in the attribute word is defined only for one type of device, a driver for the other type of device must set that bit to 0.) For character devices: Bit Value Meaning 15 1 Character device 14 1 Device supports IOCTL control strings 13 1 Device supports Output Until Busy (OUB) 12 RESERVED 11 1 Device understands OPEN/CLOSE 10-7 RESERVED 6 1 Device supports 3.2 functions 5-4 RESERVED 3 1 Device is CLOCK device 2 1 Device is NUL device 1 1 Device is console output (STO) 0 1 Device is console input (STI) For Block Devices: Bit Value Meaning 15 0 Block device 14 1 Device supports IOCTL control strings 13 1 Device determines the media by examining the FATID byte. 12 RESERVED 11 1 Device understands OPEN/CLOSE/Removable Media. MS-DOS DEVICE DRIVERS Page 2-8 10-7 RESERVED 6 1 Device supports 3.2 functions 5-0 RESERVED For example, assume that you have a new device driver that you want to use as the standard input and output. In addition to installing the driver, you must tell MS-DOS that you want this new driver to override the current standard input and standard output (the CON device). You do this by setting bits 0 and 1 to 1 (note that they are separate!). Similarly, you could install a new CLOCK device by setting the appropriate attribute. (Refer to Section 2.10, "The CLOCK Device," in this chapter for more information.) Although there is a NUL device attribute, you cannot reassign the NUL device. This attribute exists so that MS-DOS can determine whether the NUL device is being used. The IOCTL bit, bit 14, allows IOCTL functions to send and receive data to character and block devices for their own use. This allows them to set baud rate, stop bits, form length, 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 the device must not treat this information as normal I/O. This bit tells MS-DOS whether the device can handle control strings via the IOCTL system call, Function 44H. If a driver cannot process control strings, it should set this bit initially to 0. This tells MS-DOS to return an error if an attempt is made (via Function 44H) to send or receive control strings to this device. A device which can process control strings should initialize the IOCTL bit to 1. For drivers of this type, MS-DOS makes calls to the IOCTL INPUT and OUTPUT device functions to send and receive IOCTL strings. For block devices, bit 13 affects the operation of the BUILD BPB (BIOS Parameter Block) device call. If set, it requires the first sector of the FAT to reside ALWAYS in the same place. Bit 13 has a different meaning on character devices, indicating that the device implements the OUTPUT UNTIL BUSY device call. The OPEN/CLOSE/RM bit, bit 11, signals to MS-DOS 3.x, and later versions, whether this driver supports additional MS-DOS 3.0 functionality. But to support these old drivers, it is necessary to detect them. Bit 11 was reserved in MS-DOS 2.x, and is 0. All new devices, however, should support the OPEN, CLOSE, and REMOVABLE MEDIA calls and set this bit to 1. Since MS-DOS 2.x never makes these calls, the driver will be backwardly compatible. The MS-DOS 3.2 bit, bit 6, signals whether the device supports logical drive mapping via Function 440EH (Get Logical Drive Map) and Function 440FH (Set Logical Drive MS-DOS DEVICE DRIVERS Page 2-9 Map). This bit also supports generic IOCTL functions via Function 440C (Generic IOCTL for Handles) and Function 440D (Generic IOCTL for Block Devices). 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ____________________________________________________________ | C | I | O | | O | | | | | 3 | | | C | N | S | S | | H | O | Y | | P | | | | | . | | | L | U | T | T | | R | C | B | | N | | | | | 2 | | | K | L | O | I | |___|___|___|___|___|___|__|__|__|___|__|__|___|___|___|___| Figure 2.? Attribute Word for character devices 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ____________________________________________________________ | | I | F | | O | | | | | 3 | | | | | | | | | O | A | | P | | | | | . | | | | | | | | | C | T | | N | | | | | 2 | | | | | | | |___|___|___|___|___|___|__|__|__|___|__|__|___|___|___|___| Figure 2.? Attribute Word for block devices 2.5.3 Strategy And Interrupt Routines These two fields are the pointers to the entry points of the strategy and interrupt routines. They are word values, so they must be in the same segment as the device header. 2.5.4 Name Field This is an 8-byte field that contains the name of a character device or the number of units of a block device. If it is a block device, the number of units can be put in the first byte. This is optional, because MS-DOS fills in this location with the value returned by the driver's INIT code. Refer to Section 2.4, "Installation of Device Drivers," for more information. 2.6 REQUEST HEADER When MS-DOS calls a device driver to perform a function, it passes a request header in ES:BX to the strategy entry point. This is a fixed length header, followed by data pertinent to the function being performed. Note that it is the device driver's responsibility to preserve the machine state (for example, save all registers including flags on entry and restore them on exit). There is enough room on the stack to do about 20 pushes, when MS-DOS calls either the strategy or the interrupt routines. If more stack is MS-DOS DEVICE DRIVERS Page 2-10 needed, the driver should set up its own stack. The following figure illustrates a request header. REQUEST HEADER -> +-----------------------------+ | BYTE Length of record | | Length in bytes of this | | request header | +-----------------------------+ | BYTE Unit code | | The subunit the operation | | is for (minor device) | | (no meaning on character | | devices) | +-----------------------------+ | BYTE Command code | +-----------------------------+ | WORD Status | +-----------------------------+ | 8 BYTES Reserved | | | |-----------------------------| Figure 2.2. Request Header The request header fields are described below. 2.6.1 Length of Record This field contains the length (in bytes) of the request header. 2.6.2 Unit Code Field The unit code field identifies which unit in your device driver the request is for. For example, if your device driver has 3 units defined, the possible values of the unit code field would be 0, 1, and 2. 2.6.3 Command Code Field The command code field in the request header can have the following values: Command Function Code 0 INIT MS-DOS DEVICE DRIVERS Page 2-11 1 MEDIA CHECK (Block devices only) 2 BUILD BPB (Block devices only) 3 IOCTL INPUT (Only called if device has IOCTL) 4 INPUT (read) 5 NON-DESTRUCTIVE INPUT NO WAIT (Char devs only) 6 INPUT STATUS (Char devs only) 7 INPUT FLUSH (Char devs only) 8 OUTPUT (write) 9 OUTPUT (Write) with verify 10 OUTPUT STATUS (Char devs only) 11 OUTPUT FLUSH (Char devs only) 12 IOCTL OUTPUT (Only called if device has IOCTL) 13 DEVICE OPEN (Only called if OPEN/CLOSE/RM bit set) 14 DEVICE CLOSE (Only called if OPEN/CLOSE/RM bit set) 15 REMOVABLE MEDIA (Only called if OPEN/CLOSE/RM bit set and device is block) 16 OUTPUT UNTIL BUSY (Only called if bit 13 is set on character devices) 19 Generic IOCTL Request (Only called if bit 0 is set for block devices) 23 Get Drive Map (Only called if bit 6 is set on block devices) 24 Set Drive Map (Only called if bit 6 is set on block devices) Unused command codes are reserved. 2.6.4 Status Field The following figure illustrates the status field in the request header. 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 | | S | N | | | | | Y | E | | +---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+ The status word is zero on entry and is set by the driver interrupt routine on return. Bit 8 is the done bit. When set, it means the operation has completed. The driver sets it to 1 when it exits. Bit 15 is the error bit. If it is set, the low 8 bits indicate the error. The errors are: 0 Write protect violation 1 Unknown unit 2 Drive not ready MS-DOS DEVICE DRIVERS Page 2-12 3 Unknown command 4 CRC error 5 Bad drive request structure length 6 Seek error 7 Unknown media 8 Sector not found 9 Printer out of paper A Write fault B Read fault C General failure D Reserved E Reserved F Invalid disk change Bit 9 is the busy bit, which is set only by status calls and the removable media call. 2.7 DEVICE DRIVER FUNCTIONS Device drivers may perform all or some of these nine general functions. In some cases, these functions break down into several command codes. Each is described in this section. 1. INIT 2. MEDIA CHECK 3. BUILD BPB 4. READ or WRITE or WRITE TIL BUSY or Write with Verify or Read IOCTL or Write IOCTL 5. NON DESTRUCTIVE READ NO WAIT 6. OPEN or CLOSE (3.x) 7. REMOVABLE MEDIA (3.x) 8. STATUS 9. FLUSH 10. Generic IOCTL 11. Get Logical Device 12. Set Logical Device All strategy routines are called with ES:BX pointing to the Request Header. The interrupt routines get the pointers to the Request Header from the queue in which the strategy MS-DOS DEVICE DRIVERS Page 2-13 routines store them. The command code in the request header tells the driver which function to perform and what data follows the request header. ------------------------------------------------------------ | | | Note | | | | All DWORD pointers are stored offset first, segment | | second. | | | |__________________________________________________________| 2.7.1 INIT Command code = 0 INIT - ES:BX -> +------------------------------------+ | 13-BYTE Request header | +------------------------------------+ | BYTE Number of units | +------------------------------------+ | DWORD End Address | +------------------------------------+ | DWORD Pointer to BPB array | | (Not set by character devices) | +------------------------------------+ | BYTE Block device number | +------------------------------------+ One of the functions defined for each device driver is INIT. This routine is called only once when the device is installed. The INIT routine must return the END ADDRESS, which is a DWORD pointer to the end of the resident portion of the device driver. To save space you can use this pointer method to delete init code that is needed only once. The driver sets the number of units, end address, and BPB pointer. For installable block device drivers, the DWORD pointer to BPB array now points to the first character after the equal sign (=) on the line in CONFIG.SYS (the line that caused this device to be loaded). This line is terminated by a RETURN or a linefeed. This data is read-only and lets the device driver scan the CONFIG.SYS line for arguments. device=\dev\vt52.sys /l ^ |_____BPB address points here Also, the block device driver defines the first unit and assigns it to the drive number in the block device number MS-DOS DEVICE DRIVERS Page 2-14 field (for example, A=0). This field is also read-only. Installable character devices must return only the end address parameter. This parameter is a pointer to the first available byte of memory above the location of the driver and which the driver may use to throw away initialization code. Block devices must return the following information: 1. The number of units. MS-DOS uses this number to determine logical device names. At the time of the install call, if the current maximum logical device letter is F, and the INIT routine returns 4 as the number of units, these units will have logical names G, H, I and J. This mapping is determined by the position of the driver in the device list and by the number of units on the device (stored in the first byte of the device name field). 2. A DWORD pointer to an array of one-word offsets (pointers) to BPBs (BIOS Parameter Blocks). MS-DOS creates an internal structure by using the BPBs passed by the device driver. There must be one entry in this array for each unit defined by the device driver. In this way, if all units are the same, all the pointers can point to the same BPB, saving space. If the device driver defines two units, the DWORD pointer points to the first of two one-word offsets. In turn these offsets point to BPBs. The format of the BPB is described later in this chapter in Section 2.7.3, "BUILD BPB." Note that this array of one-word offsets must not be above the free pointer set by the return, because the device driver builds an internal DOS structure, starting at the byte pointed to by the free pointer. The defined sector size must be less than or equal to the maximum sector size defined by the resident device drivers (BIOS) during initialization. If it isn't, the installation will fail. 3. The media descriptor byte. This byte, which is the last byte returned by INIT, means nothing to MS-DOS, but is passed to devices so that they know which parameters MS-DOS is currently using for a particular drive unit. Block devices may be either dumb or smart. A dumb device ____ _____ defines a unit (and therefore an internal DOS structure) for MS-DOS DEVICE DRIVERS Page 2-15 each possible media-drive combination. For example, unit 0 = drive 0, single sided; unit 1 = drive 0, double sided. For the "dumb device" approach, media descriptor bytes do not mean anything. A smart device allows multiple media per unit. In the case of a smart device, the BPB table returned upon INIT must define sufficient space to accommodate the largest possible media. Smart drivers use the media descriptor byte to pass information about what media is currently in a unit. For more information on the media descriptor byte, see Section 2.8, "Media Descriptor Byte." ------------------------------------------------------------ | | | Note | | | | If a file contains multiple device drivers, MS-DOS uses | | the ending address returned by the last INIT called. | | All the device drivers in a single file should return | | the same ending address. The code to remain resident | | for all the devices in a file should be grouped | | together in low memory with the initialization code for | | all devices following it. | | | |__________________________________________________________| 2.7.2 MEDIA CHECK Command Code = 1 MEDIA CHECK - ES:BX -> +------------------------------------+ | 13-BYTE Request header | +------------------------------------+ | BYTE Media descriptor from BPB | +------------------------------------+ | BYTE Returned | +------------------------------------+ | Returned DWORD pointer to previous | | Volume ID if bit 11 set and | | Media Changed is returned | +------------------------------------+ The MEDIA CHECK function is used with block devices only. It is called when there is a pending drive access call other than a file read or write, such as open, close, delete, or rename. Its purpose is to determine whether the media in the drive has been changed. If the driver can ensure that MS-DOS DEVICE DRIVERS Page 2-16 the media has not been changed (through a door-lock or other interlock mechanism), MS-DOS does not need to reread the FAT and invalidate in-memory buffers for each directory access. When such a disk access call to the DOS occurs (other than a file read or write), the following sequence of events takes place: 1. The DOS converts the drive letter into the unit number of a particular block device. 2. The device driver is then called to request a media check on that subunit to see if the disk might have been changed. MS-DOS passes the old media descriptor byte. The driver returns: Media not changed...... (1) Don't know if changed...(0) Media changed...........(-1) Error If the media has not been changed, MS-DOS proceeds with the disk access. If the value returned is "Don't know," and if there are any disk sectors that have been modified and not yet written back to the disk for this unit, MS-DOS assumes that the disk has not been changed and proceeds. MS-DOS invalidates any other buffers for the unit and does a BUILD BPB device call (see step 3, below). If the media has been changed, MS-DOS invalidates all buffers associated with this unit including buffers with modified data that are waiting to be written, and requests a new BIOS Parameter Block via the BUILD BPB call (see step 3, below). 3. Once the BPB has returned, MS-DOS corrects its internal structure for the drive from the new BPB and, after reading the directory and the FAT, proceeds with the access. Note that the previous media ID byte is passed to the device driver. If the old media ID byte is the same as the new one, the disk might have been changed and a new disk may be in the drive. Therefore, all FAT, directory, and data sectors that are buffered in memory for the unit are considered invalid. If the driver has bit 11 of the device attribute word set to 1, and the driver returns -1, "Media Changed," it must set MS-DOS DEVICE DRIVERS Page 2-17 the DWORD pointer to the previous Volume ID field. If the DOS determines that "Media Changed" is an error based on the state of the DOS buffer cache, it generates a 0FH error on behalf of the device. If the driver does not implement Volume ID support, but has bit 11 set, it should set a static pointer to the string, "NO NAME",0. It is not possible for a user to change a disk in less than 2 seconds. So when MEDIA CHECK occurs within 2 seconds of a disk access, the driver reports "1," "Media not changed." This action increases performance tremendously. ------------------------------------------------------------ | | | Note | | | | For MS-DOS versions before 3.2 if the media ID byte in | | the returned BPB is the same as the previous media ID | | byte, MS-DOS assumes that the format of the disk is the | | same (even though the disk may have been changed) and | | skips the step of updating its internal structure. All | | BPBs, therefore, must have unique media bytes regardless| | of FAT ID bytes. | | | |__________________________________________________________| 2.7.3 BUILD BPB (BIOS Parameter Block) Command code = 2 BUILD BPB - ES:BX -> +------------------------------------+ | 13-BYTE Request header | +------------------------------------+ | BYTE Media descriptor from BPB | +------------------------------------+ | DWORD Transfer address | | (Points to one sector worth of | | scratch space or first sector | | of FAT depending on the value | | of Bit 13 in the device attribute | | word.) | +------------------------------------+ | DWORD Pointer to BPB | +------------------------------------+ The Build BPB function is used with block devices only. As described in the MEDIA CHECK function, the BUILD BPB function is called any time that a preceding MEDIA CHECK call indicates that the disk has been, or might have been, MS-DOS DEVICE DRIVERS Page 2-18 changed. The device driver must return a pointer to a BPB. This is different from the INIT call where the device driver returns a pointer to an array of word offsets to BPBs. The BUILD BPB call gets a DWORD pointer to a one-sector buffer. The contents of this buffer are determined by the NON FAT ID bit (bit 13) in the attribute field. If the bit is zero, the buffer contains the first sector of the first FAT. The FAT ID byte is the first byte of this buffer, so in this case, the driver must not alter the buffer. Note that the location of the FAT must be the same as for all possible media because the DOS must read this FAT sector before the driver returns the BPB that the DOS called. If the NON FAT ID bit is set, the pointer points to one sector of scratch space (space which may be used for anything). Refer to Section 2.8, "Media Descriptor Byte,"" and Section 2.9, "Format of a Media Descriptor Table," for information on how to construct the BPB. MS-DOS 3.x includes additional support for devices that have door-locks or some other means of telling when a disk has been changed. Error 15, a new error that the device driver can return, means "the disk has been changed when it shouldn't have been." The user is prompted for the correct disk using a Volume ID. The driver may generate this error for READ or WRITE. The DOS may generate the error for MEDIA CHECK if the driver reports media changed, and there are buffers in the DOS buffer cache that need to be flushed to the previous disk. For drivers that support this error, the BUILD BPB function is a trigger that causes the driver to read a new Volume ID from the disk. This action indicates that the disk has been legally changed. The FORMAT or LABEL utility places a Volume ID on the disk. This ID is simply an entry in the root directory of the disk that has the Volume ID attribute. The driver stores the Volume ID as an ASCIZ string. The requirement that the driver return a Volume ID does not exclude some other Volume identifier scheme as long as the scheme uses ASCIZ strings. A NUL (nonexistent or unsupported) Volume ID is by convention the string: DB "NO NAME ",0 MS-DOS DEVICE DRIVERS Page 2-19 2.7.4 READ or WRITE Command codes = 3,4,8,9, 12, and 16 READ OR WRITE (Including IOCTL) or OUTPUT UNTIL BUSY - ES:BX -> +------------------------------------+ | 13-BYTE Request header | +------------------------------------+ | BYTE Media descriptor from BPB | +------------------------------------+ | DWORD Transfer address | +------------------------------------+ | WORD Byte/sector count | +------------------------------------+ | WORD Starting sector number | | (Ignored on character devices) | +------------------------------------+ | Returned DWORD pointer to requested| | Volume ID if error 0FH | +------------------------------------+ COMMAND CODE REQUEST 3 IOCTL READ 4 READ (block or character) 8 WRITE (block or character) 9 WRITE WITH VERIFY 12 IOCTL WRITE 16 OUTPUT TIL BUSY (char devs only) The driver must perform the READ or WRITE call depending on which command code is set. Block devices read or write sectors; character devices read or write bytes. When I/O completes, the device driver must set the status word and report the number of sectors or bytes successfully transferred, even if an error prevented the transfer from being completed. Setting the error bit and error code alone _______ ___ _____ ___ ___ _____ ____ _____ is not sufficient.__ ___ __________ In addition to setting the status word, the driver must set the sector count to the actual number of sectors (or bytes) transferred. No error check is performed on an IOCTL I/O call. If the verify switch is on, the device driver is called with command code 9 (WRITE WITH VERIFY). Your device driver is then responsible for verifying the write. If the driver returns error code 0FH (Invalid disk change), it must return a DWORD pointer to an ASCIZ string (which is the correct Volume ID). The return of this error code triggers the DOS to prompt the user to re-insert the disk. The device driver should have read the Volume ID as a result of the BUILD BPB function. Drivers may maintain a reference count of open files on the disk by monitoring the OPEN and CLOSE functions. This allows the driver to determine when to return error 0FH. If there are no open files (reference count = 0), and the disk MS-DOS DEVICE DRIVERS Page 2-20 has been changed, the I/O is okay. If there are open files, however, an 0FH error may exist. The OUTPUT UNTIL BUSY call is a speed optimization on character devices only for print spoolers. The device driver is expected to output all the characters possible until the device returns busy. Under no circumstances should the device driver block during this function. Note that it is not an error if the device driver returns a smaller number of bytes output than bytes requested. The OUTPUT UNTIL BUSY call allows spooler programs to take advantage of the burst behavior of most printers. Many printers have on-board RAM buffers which typically hold a line or a fixed amount of characters. These buffers fill up without making the printer "busy" between characters for a relatively short time (or at least not for more than ten instructions). The device driver can quickly output a line of characters to the printer, which is then busy for a comparatively longer time while it prints. This new device call allows background spooling programs to use this burst behavior efficiently. Rather than take the overhead of a device driver call for each character, or risk getting stuck in the device driver outputting a block of characters, this call allows a burst of characters to be output without the device driver having to wait until the device is ready. If the MS-DOS 3.2 bit is set, then MS-DOS can configure the number of retries (allowed by the device driver) that the printer can make before returning "busy." THE FOLLOWING APPLIES TO BLOCK DEVICE DRIVERS:___ _________ _______ __ _____ ______ _______ Under certain circumstances, the device driver may request that the BIOS perform a write operation of 64K bytes, which seems to be a "wrap around" of the transfer address in the BIOS I/O packet. This request arises due to an optimization added to the write code in MS-DOS. It will only manifest itself on user writes within a sector size of 64K bytes to files "growing" past the current EOF. The BIOS may ignore ___ ____ ___ ______ the balance of the write that "wraps around," if it so___ _______ __ ___ _____ ____ ______ ________ __ __ __ chooses. For example, a write of 10000H bytes worth of________ sectors with a transfer address of XXX:1 could ignore the last two bytes. A user program can never request an I/O of more than FFFFH bytes and cannot wrap around (even to 0) in the transfer segment. Therefore, in this case the BIOS ignores the last two bytes. MS-DOS maintains two FATs. If the DOS has problems reading the first, it automatically tries the second before reporting the error. The BIOS is responsible for all retries. Although the COMMAND.COM handler does no automatic retries, there are applications that have their own Interrupt 24H MS-DOS DEVICE DRIVERS Page 2-21 handlers. These handles do automatic retries on certain types of Interrupt 24H errors before reporting them. 2.7.5 NON DESTRUCTIVE READ NO WAIT Command code = 5 NON DESTRUCTIVE READ NO WAIT - ES:BX -> +------------------------------------+ | 13-BYTE Request header | +------------------------------------+ | BYTE read from device | +------------------------------------+ This call lets MS-DOS look ahead one input character. The device sets the done bit in the status word. If the character device returns busy bit = 0, characters are in the buffer and the next character that would be read is returned. This character is not removed from the input ___ buffer (hence the term "Non Destructive Read"). If the character device returns busy bit = 1, there are no characters in the buffer. 2.7.6 OPEN or CLOSE Command codes = 13 and 14 OPEN or CLOSE - ES:BX -> +------------------------------------+ | 13-BYTE Static request header | +------------------------------------+ These functions are called by MS-DOS 3.x only if the device driver sets the OPEN/CLOSE/RM attribute bit in the device header. They are designed to inform the device about its current file activity. On block devices, these functions can manage local buffering, and the device can keep a reference count. Every OPEN causes the device to increment the count, every CLOSE to decrement. When the count goes to zero no open files are on the device. Also, the device should flush any buffers that it may have used in case the media has been changed. Block devices can have problems with this mechanism because programs that use FCB calls can open files without closing MS-DOS DEVICE DRIVERS Page 2-22 them. Therefore, when the media has been changed and the BUILD BPB call has been made to the device, you should reset the count to zero without flushing the buffers. These calls are more useful on character devices. For example, the device could use the OPEN call to send a device initialization string. For example, this string might set a printer's default characteristics for font and page size. Using IOCTL to set these pre- and post-strings provides a flexible mechanism of serial I/O device stream control. A driver could also use the reference count mechanism to detect a simultaneous access error. You may not want to allow more than one OPEN on a device at any given time, since, in this case, a second OPEN would result in an error. Note that since all processes have access to stdin, stdout, stderr, stdaux, and stdprn (handles 0,1,2,3,4), the CON, AUX, and PRN devices are always open. ______ 2.7.7 REMOVABLE MEDIA Command code = 15 REMOVABLE MEDIA - ES:BX -> +------------------------------------+ | 13-BYTE Static request header | +------------------------------------+ This function is called by MS-DOS 3.x only if the device driver sets the OPEN/CLOSE/RM attribute bit in the device header. Only a subfunction of the IOCTL system call can issue this call to block devices. Sometimes it is necessary for a utility to know whether it is using a non-removable media drive (a hard disk), or a removable media drive (a floppy). For example, the FORMAT utility prints different prompts depending on the media. The information returns in the busy bit of the status word. If the busy bit is 1, the media is non-removable, and if the busy bit is 0, the media is removable. Note that the device driver does not check the error bit; it just assumes that this call always succeeds. MS-DOS DEVICE DRIVERS Page 2-23 2.7.8 STATUS Command codes = 6 and 10 STATUS Calls ES:BX -> +------------------------------------+ | 13-BYTE request header | +------------------------------------+ This call returns information to the DOS to let it know if data is waiting for input or output. All the driver must do is set the status word and the busy bit as follows: For output on character devices: If the driver ___ ______ __ _________ _______ sets bit 9 to 1 on return, it informs the DOS that a write request (if made) would wait for completion of a current request. If bit 9 is 0, there is no current request and a write request (if made) would start immediately. For input on character devices with a buffer: If ___ _____ __ _________ _______ ____ _ ______ bit 9 equals 1 this implies that the buffer is empty and that a read request (if made) would go to the physical device. If bit 9 is 0 on return, characters are in the device buffer and a read request would start immediately. A return of 0 implies that you have typed something. MS-DOS assumes that all character devices have an input type-ahead buffer; devices that do not should always return busy = 0 so that the DOS does not wait for you to put something into a non-existent buffer. 2.7.9 FLUSH Command codes = 7 and 11 FLUSH Calls - ES:BX -> +------------------------------------+ | 13-BYTE request header | +------------------------------------+ The FLUSH call tells the driver to flush (terminate) all pending requests. This call is used to flush the input queue on character devices. The device driver performs the flush function, sets the status word, and returns. MS-DOS DEVICE DRIVERS Page 2-24 2.7.10 Generic IOCTL Request Command code = 19 ES:BX --> +----------------------------------+ | 13-BYTE Static Request Header | +----------------------------------+ | BYTE Category (Major) Code | +----------------------------------+ | BYTE Function (Minor) Code | +----------------------------------+ | WORD (SI) contents | +----------------------------------+ | WORD (DI) contents | +----------------------------------+ | DWORD pointer to data buffer | +----------------------------------+ This function provides a generic, expandable IOCTL facility that replaces and makes the Read IOCTL and Write IOCTL device driver functions obsolete. The MS-DOS 2.0 IOCTL functions remain to support existing uses of the IOCTL system call (subfunctions 2, 3, 4 and 5), but new device drivers should use this generic MS-DOS IOCTL facility. The generic IOCTL function contains both a category and function code. The DOS examines the category field in order to intercept and obey device commands that are actually serviced by the DOS code; all other command categories are forwarded to the device driver for servicing. For more information on these category and function codes, refer to Functions 440CH (Generic IOCTL for handles) and Function 440DH (Generic IOCTL for block devices) in Chapter 1, "System Calls." 2.7.11 Get/Set Logical Drive Map Command code = 23 (Get) or 24 (Set) +-------------------------------------------+ | 13-byte Static Request Header | +-------------------------------------------+ | BYTE Input (unit code) | +-------------------------------------------+ | BYTE Output (last device referenced) | +-------------------------------------------+ | BYTE Command code | +-------------------------------------------+ | WORD Status | +-------------------------------------------+ | DWORD Reserved | +-------------------------------------------+ This function is only called by MS-DOS if the device driver sets the DOS 3.2 attribute bit in the device header. The call is only issued to block devices by a subfunction of the IOCTL system call. The logical drive is passed in the UNIT field of the header to the device driver, which returns the MS-DOS DEVICE DRIVERS Page 2-25 current logical drive that is mapped on the physical drive in the UNIT field of the header. 2.8 MEDIA DESCRIPTOR BYTE In MS-DOS, the media descriptor byte informs the DOS that a different type of media is present. The media descriptor byte can be any value between 0 and FFH. It does not have to be the same as the FAT ID byte. The FAT ID byte, which is the first byte of the FAT, was used in MS-DOS 1.00 to distinguish between different types of disk media. This byte may also be used under 2.x and 3.x disk device drivers. However, FAT ID bytes have significance only for block device drivers where the NON FAT ID bit is not set (0). Values of the media descriptor byte or the FAT ID byte have no significance to MS-DOS. They are passed directly to the device driver so that programs can determine the media type. 2.9 FORMAT OF A MEDIA DESCRIPTOR TABLE The MS-DOS file system uses a linked list of pointers (one for each cluster or allocation unit) called the File Allocation Table (FAT). Unused clusters are represented by zero and end-of-file by FFF (or FFFF on units with 16-bit FAT entries). No valid entry should ever point to a zero entry, but if one does, the first FAT entry (which would be pointed to by a zero entry) should be reserved and set to end-of-chain. Eventually, several end-of-chain values can be defined ([F]FF8-[F]FFF), and used to distinguish different media types. A preferrable technique is to write a complete media descriptor table in the boot sector and use it for media identification. To ensure backward compatibility for systems whose drivers do not set the NON FAT ID bit (including the IBM PC implementation), it is necessary to write the FAT ID bytes during the FORMAT process. In the future to allow more flexibile support for many different disk formats, you should keep the information relating to the BPB for a particular media in the boot sector. Figure 2.3 shows the format of such a boot sector. MS-DOS DEVICE DRIVERS Page 2-26 +------------------------------------+ | 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 sectors per FAT | ---+------------------------------------+--- | WORD Sectors per track | +------------------------------------+ | WORD Number of heads | +------------------------------------+ | WORD Number of hidden sectors | +------------------------------------+ | WORD High order number of hidden | | sectors | +------------------------------------+ | DWORD Number of logical sectors | +------------------------------------+ Figure 2.3. Format of Boot Sector Although MS-DOS does not use the five fields that follow the BPB, they may be used by a device driver to help it understand the media. The "Sectors per track" and "Number of heads" fields are useful for supporting different media which may have the same logical layout, but a different physical layout (e.g., 40 track double-sided versus 80 track single-sided). "Sectors per track" tells the device driver how the logical disk format is laid out on the physical disk. The "Number of hidden sectors" and the "High order number of hidden sectors" fields may be used to suport drive-partitioning schemes. The "Number of logical sectors" field is not currently used but will tell the device driver how many sectors to reserve if the "Number of sectors in logical image" field is zero. MS-DOS DEVICE DRIVERS Page 2-27 (This is intended for supporting drives that access more than 32 megabytes.) NON FAT ID format drivers should use the following procedure to determine media type: 1. Read the boot sector of the drive into the 1-sector scratch space pointed to by the DWORD Transfer address. 2. Determine whether the first byte of the boot sector is either E9H (the first byte of a 3-byte NEAR or 2-byte short jump) or EBH (the first byte of a 2-byte jump followed by a NOP). If it is, return a pointer to a BPB beginning at offset 3. 3. If the boot sector does not have a BPB table, it is probably a disk formatted under a 1.x version of MS-DOS. Therefore, it probably uses a FAT ID byte for determining media. As an option, the driver may attempt to read the first sector of the FAT into the 1-sector scratch space and then read the first byte to determine the media type. Return a pointer to a hard-coded BPB. 2.10 THE CLOCK DEVICE MS-DOS assumes that some sort of clock is available in the system. This clock may be either a CMOS real-time clock or an interval timer which the user initializes at boot time. The CLOCK device defines and performs functions like any other character device except that the DOS identifies it by a bit in the attribute word. Consequently this device may take any name. The IBM version uses "$CLOCK" to avoid conflict with existing files named "CLOCK." The CLOCK device is unique because MS-DOS reads or writes a 6-byte sequence that encodes the date and time. A write to this device sets the date and time, and a read gets the date and time. Figure 2.4 illustrates the binary time format which the CLOCK device uses: MS-DOS DEVICE DRIVERS Page 2-28 byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 +--------+--------+---------+--------+--------+---------+ | | | | | | | |days since 1-1-80| minutes | hours | sec/100| seconds | |low byte|hi byte | | | | | +--------+--------+---------+--------+--------+---------+ Figure 2.4. CLOCK Device Format 2.11 ANATOMY OF A DEVICE CALL The following steps illustrate what happens when MS-DOS calls on a block device driver to perform a WRITE request: 1. MS-DOS writes a request packet in a reserved area of memory. 2. It then calls the block device driver strategy entry point. 3. The device driver saves the ES and BX registers (ES:BX points to the request packet) and does a FAR return. 4. MS-DOS calls the interrupt entry point. 5. The device driver retrieves the pointer to the request packet and reads the command code (offset 2) to determine that this is a write request. The device driver converts the command code for an index into a dispatch table and passes control to the disk write routine. 6. The device driver reads the unit code (offset 1) to determine which disk drive it should write to. 7. Since the command is a disk write, the device driver must get the transfer address (offset 14), the sector count (offset 18), and the start sector (offset 20) in the request packet. 8. The device driver translates the first logical sector number into a track, head, and sector number. MS-DOS DEVICE DRIVERS Page 2-29 9. The device driver writes the specified number of sectors, starting at the beginning sector on the drive defined by the unit code (the subunit defined by this device driver), and transfers data from the address indicated in the request packet. Note that this may involve multiple write commands to the disk controller. 10. After the transfer is complete, the device driver must report the status of the request to MS-DOS by setting the done bit in the status word (offset 3 in the request packet). It reports the number of sectors actually transferred in the sector count area of the request packet. 11. If an error occurs, the driver sets the done bit and the error bit in the status word and fills in the error code in the lower half of the status word. The number of sectors actually transferred must be written in the request header. It is not sufficient just to set the error bit of the status word. 12. Finally, the device driver does a FAR return to MS-DOS. The device drivers should preserve the state of MS-DOS, including all registers (and flags). In particular, the direction flag and interrupt enable bits are critical. When the interrupt entry point in the device driver is called, MS-DOS has room for about 40 to 50 bytes on its internal stack. Your device driver should switch to a local stack if it uses extensive stack operations. APPENDIX E MSDOS 2.25 Device Driver Interface Extension. MSDOS 2.25 is designed so as to be able to run with CONSOLE DEVICE DRIVERS FROM PREVIOUS VERSIONS. If this is the case then no interim character processing can be done, and all character composition must be handled directly by the console device driver. The MSDOS 2.25 BIOS interface (IO.SYS) has the following differences from the standard MSDOS 2.11 BIOS. These changes are extensions to the CON (Console) Device driver for hardware which will be utilizing Interim Character support. Consult the MSDOS Adapatation Guide for overall description of device driver design and funtionality 1) On the INPUT and NON-DESTRUCTIVE INPUT calls to the device driver (DD) the DD must check bit 0 of the byte at offset 14 in the request packet. If the bit is 0 then it should return only final characters, if the bit is 1 then the device driver should return interim as well as final characters to the dos. Also on INPUT, if the request is for more than ONE byte then the DD should return ONLY final characters, no matter what the state of bit 0 in the byte at offset 14. 2) On return from INPUT, NON-DESTRUCTIVE INPUT and INPUT STATUS calls, the device driver should return to the dos with bit 10 of the status word SET if the character read, or the character available is an interim character, or the bit RESET if the character is a final character. (Pre 2.25 DD's always return with this bit reset). If more than one character is read on an INPUT call then bit 10 should be RESET as all the characters returned should be final characters (see above). 3) On Console WRITE function the device driver should check bit 0 of the byte at offset 14 in the request packet. If the bit is reset then the character should be output as a regular character by printing the character and advancing the cursor to the next position. If the bit is SET then the character is an interim character and should be treated by the device driver display routine accordingly. In most cases the character should be displayed without advancing the cursor to the next character position. When using interim 16 bit characters that are output a byte at a time, then the routine should handle this correctly, displaying the 16 bit interim and not advancing the cursor to the next character position. Special considerations / requirements. If a console device driver is going to return interim characters then the device driver MUST be able to handle the extension made to character WRITE (described above in 3). Device drivers should be able to support requests for final / interim characters in any order. Application programs may at any time change the way they want characters, and device drivers should be capable of changing without any other indication than the DD request itself. Device drivers should be capable of handling composition somehow for those applications that do not do it themselves. The keyboard typeahead buffer should be kept at the key level, without further interpretation. All processing of interims in case of an input request for a final character is issued (and there are interims in the buffer that have to be composed to obtain a final character), should be done at the time the request is done to the device driver. Sample Device Driver for DOS 2.25 Interim Character Support WARNING!! Not Assembleable. This code must be modified for the OEM's own hardware and firmware. PAGE CODE SEGMENT BYTE ASSUME CS:CODE,DS:NOTHING,ES:NOTHING ;---------------------------------------------------------------- ; ; C O N - CONSOLE DEVICE DRIVER ; DW -1,-1 DW 1000000000010011B ; CON IN AND CON OUT + Special bit DW STRATEGY DW ENTRY DB 'CON ' InterH db 0 ; Interim character flag ALTAH DB 0 ; Special key handling ;---------------------------------------------------------------- ; ; COMMAND JUMP TABLES CONTBL: DW CON$INIT DW EXIT DW EXIT DW CMDERR DW CON$READ DW CON$RDND DW EXIT DW CON$FLSH DW CON$WRIT DW CON$WRIT DW EXIT DW EXIT PAGE ;---------------------------------------------------------------- ; ; Device entry point ; CMDLEN = 0 ;LENGTH OF THIS COMMAND UNIT = 1 ;SUB UNIT SPECIFIER CMD = 2 ;COMMAND CODE STATUS = 3 ;STATUS MEDIA = 13 ;MEDIA DESCRIPTOR TRANS = 14 ;TRANSFER ADDRESS COUNT = 18 ;COUNT OF BLOCKS OR CHARACTERS START = 20 ;FIRST BLOCK TO TRANSFER BRKADR = Oem_Brk ; Break Vector Address CHROUT = 29H ; fast con int PAGE ;---------------------------------------------------------------- ; ; Entry Procedures ; PTRSAV DD 0 STRATP PROC FAR STRATEGY: MOV WORD PTR CS:[PTRSAV],BX MOV WORD PTR CS:[PTRSAV+2],ES RET STRATP ENDP ENTRY: PUSH SI PUSH AX PUSH CX PUSH DX PUSH DI PUSH BP PUSH DS PUSH ES PUSH BX LDS BX,CS:[PTRSAV] ; DS:BX points to IO packet mov cx,word ptr ds:[bx].count ; CX = count mov dl,byte ptr ds:[bx].media ; DL = input type flag mov al,byte ptr ds:[bx].cmd ; AL = command code cbw MOV SI,OFFSET CONTBL ; command table ADD SI,AX ADD SI,AX CMP AL,11 JA CMDERR ; command code out of range LES DI,DWORD PTR DS:[BX].TRANS ; transfer address PUSH CS POP DS ASSUME DS:CODE JMP WORD PTR [SI] ; GO DO COMMAND PAGE ;---------------------------------------------------------------- ; ; EXIT - ALL ROUTINES RETURN THROUGH THIS PATH ; CMDERR: MOV AL,3 ; Unknown Command Error ERR$EXIT: mov ah,10000001b ; Mark Error Return jmp short err1 BUS$EXIT: mov ah,00000011b ; Device Busy Exit jmp short err1 HanExit: mov [InterH],0 ; reset interim flag mov ah,00000101b ; Bit 10 Set for interim chars jmp short err1 EXITP PROC FAR EXIT: MOV AH,00000001B ERR1: LDS BX,CS:[PTRSAV] MOV WORD PTR [BX].STATUS,AX ; Mark Operation Complete POP BX POP ES POP DS POP BP POP DI POP DX POP CX POP AX POP SI RET ; RESTORE REGS AND RETURN EXITP ENDP PAGE ;---------------------------------------------------------------- ; ; BREAK KEY HANDLING ; BREAK: MOV CS:ALTAH,3 ; INDICATE BREAK KEY SET IRET ;---------------------------------------------------------------- ; ; CHROUT - WRITE OUT CHAR IN AL USING CURRENT ATTRIBUTE ; ; CALLED VIA INT 29H ; OUTCHR: INT OEM_Char_Output RET PAGE ;---------------------------------------------------------------- ; ; INPUT SINGLE CHAR INTO AL ; ChrIn: xor ax,ax xchg al,ALTAH ; Get Character & Zero ALTAH or al,al jnz sj3 mov ah,Request_Interim ; assume interim char input or dl,dl ; Interim chars wanted? jnz sj0 mov ah,Request_Char ; regular whole char input sj0: int OEM_Kybd_Input ; Get character or ax,ax ; Check for non-key after BREAK jz ChrIn or al,al ; Special Case? jnz ChkInter mov ALTAH,ah ; Save Special Key sj3: mov [InterH],0 ; reset interim flag ret ChkInter: cmp ah,Hangeul_Interim ; a Hangeul interim? jne sj3 mov [InterH],1 ; yes flag it ret PAGE ;---------------------------------------------------------------- ; ; CONSOLE READ ROUTINE ; ; Input: ; CX = transfer count ; DL = input type flag (0 = whole chars, 1 = interim allowed) ; ES:DI = transfer addess ; CON$READ: JCXZ CON$EXIT CON$LOOP: CALL CHRIN ; GET CHAR IN AL STOSB ; STORE CHAR AT ES:DI LOOP CON$LOOP CON$EXIT: cmp [InterH],1 ; An Intermidiate Char? jne ExVec ; no, regulear exit JMP HanExit ; yes, reset flag and exit new way PAGE ;---------------------------------------------------------------- ; ; KEYBOARD FLUSH ROUTINE ; CON$FLSH: MOV [ALTAH],0 ; Clear out holding buffer mov [InterH],0 mov ah,Flush_Buffer int OEM_Kybd_Input JMP EXIT PAGE ;---------------------------------------------------------------- ; ; KEYBOARD NON DESTRUCTIVE READ, NO WAIT ; Input: ; DL = input type flag (0 = whole chars, 1 = interim allowed) ; EXVEC: JMP EXIT CONBUS: JMP BUS$EXIT CON$RDND: MOV AL,[ALTAH] OR AL,AL JNZ sj6 MOV AH,Request_Interim_Status ;Assume interim allowed or dl,dl ; check interim flag jnz sj4 mov ah,Requst_Std_Status ; regular status wanted sj4: INT OEM_Kybd_Input ; Get status JZ CONBUS OR AX,AX JNZ sj6 ; CHECK FOR NULL AFTER BREAK MOV AH,Request_Char INT OEM_Kybd_Input ; READ THE NULL JMP short CON$RDND ; AND GET A REAL STATUS sj6: MOV [InterH],0 ; not interim sj7: LDS BX,[PTRSAV] MOV [BX].MEDIA,AL ; return the char to dos cmp [InterH],0 je EXVEC jmp HanExit sj8: cmp ah,Interim_Char ; a Hangeul interim? jne sj6 mov [InterH],1 jmp short sj7 PAGE ;---------------------------------------------------------------- ; ; CONSOLE WRITE ROUTINE ; CON$WRIT: JCXZ EXVEC cmp dl,01h ; write and not ad cursor? je CON$LP2 CON$LP: MOV AL,ES:[DI] ; GET CHAR INC DI MOV AH,Output_Char INT CHROUT ; OUTPUT CHAR LOOP CON$LP ; REPEAT UNTIL ALL THROUGH JMP EXIT CON$LP2: ; write but do not advance cursor MOV AL,ES:[DI] ; GET CHAR INC DI MOV AH,Output_No_Advance INT CHROUT LOOP CON$LP2 ; REPEAT UNTIL ALL THROUGH JMP EXIT PAGE ;---------------------------------------------------------------- ; ; Initialization Code ; CON$INIT: XOR BX,BX MOV DS,BX MOV BX,BRKADR MOV WORD PTR [BX],OFFSET BREAK MOV WORD PTR [BX+2],CS MOV BX,CHROUT*4 MOV WORD PTR [BX],OFFSET OUTCHR MOV WORD PTR [BX+2],CS LDS BX,CS:[PTRSAV] MOV WORD PTR [BX].TRANS,OFFSET CON$INIT ; SET BREAK ADDRESS MOV [BX].TRANS+2,CS JMP EXIT CODE ENDS END APPENDIX F MSDOS 2.25 Application Level Interface Extension 1) System call 63H, get_lead_tbl. This call takes an argument in register AL. This argument determines what function will this call execute. Valid values for the function code are 0, 1 and 2. If AL = 0, then the call returns in DS:SI a pointer to a table containing the lead byte ranges for the 16 bit alphabet in question. The table consists of byte pairs that are the boundaries for the lead bytes (both values inclusive). The end of the table is marked by two zero byte entries. Example, for japanese kanji the table would look like db 81H,9FH db 0E0h,0FCh db 0,0 Note that the values should be read as byte values not as word values since otherwise the ranges would be transposed due to the byte ordering in the 8086/88. This table is empty in the regular version of the dos (as there are no 16 bit characters). The table if obtained would point to a pair of zero bytes. If AL = 1 then the call will set (or reset) the interim console flag in the dos depending on the value in DL. If DL = 1, then the interim flag will be SET, and certain console system calls will return interim characters if these are available. If DL = 0 then the interim flag is RESET and only final characters will be returned. The default value of the flag is RESET. All application programs start with the flag RESET. The flag is allways restored to the parents setting when an application terminates. If AL = 2 then the dos will return in DL the current value of the console interim flag (0 if RESET, 1 if SET). If an invalid code is used the call will reurn with carry set and error code 0 (error_invalid_function). IMPORTANT NOTE: This system call unlike all other system calls make NO GUARANTEE to preserve ANY registers other than SS:SP upon return. So care should be taken to save all relevant registers before issuing the call. It is advisable that an application either copy the table to its private data area or save the pointer to the table at initialization time. This should save considerable execution time as there is no need to reissue the call everytime a check for 16 bit characters is necessary, and consequently there is no need to save any registers before issuing the call. 2) Console i/o system calls. Some console i/o system calls are capable of returning interim character information to application programs. Only those applications that have enabled the feature through the 63H call (function 1) will receive interim characters on these system calls, otherwise the dos will never return interim characters and the system calls will work as in previous versions of 2.00. * Call 01H, Read & Echo. This call never returns interim characters no matter what mode the console is on. Composition if any will take place at the cursor. It will return when the first byte of the final character is obtained. * Call 06H, Direct Console i/o. Always returns final characters, never interims. Only returns character available when a final character is available, not when interims are available. Composition if any is handled as in call 01H. * Call 07H, Direct Console Input. Returns interim characters if one is available and the console mode has been set to interim through the 63H call. Interim characters are returned with the zero flag SET, final characters have the flag RESET. In non interim support (the default) the zero flag value is undefined. * Call 08H, Read Keyboard. Same as system call 07H. * Call 0AH, Buffered Keyboard input. Always returns a string of final characters, composition if any, is handled by the dos. * Call 0BH, Check Keyboard Status. This call supports interim characters if the console has been placed in interim mode through the ioctl call. If a character is available (AL = 0FFH) then the zero flag will be SET if the character is an interim, or RESET if the character is a final character. The zero flag is undefined if either there is no character available, or the console is not in interim mode. * Call 0CH, Flush Buffer, Read Keyboard. This call will flush the type-ahead buffer and execute the specified console i/o call. The con i/o call will work as described above for each specific case. * Call 3FH, Xenix Read. This call always returns final characters, no matter what the state of the dos. This call when directed to the console it ends up in the buffered console input code, and so it will act as that call (0AH) when used to read from the console. APPENDIX G This file is part of what was formerly supplied with MS-DOS 2.11 as SPECIAL.DOC. It has information about undocumented COMMAND.COM switches and the version dependent system call (GET_DPB) which OEM's may use when writing format. The remaining portions of this file have been incorporated into printed MS-DOS documentation. COMMAND invocation COMMAND [[:]] [] [/D] [/P] [/C ] [/E:nnnn] /P If present COMMAND will be permanent, otherwise this is a transient command. /D If present COMMAND will not prompt for DATE and TIME when it comes up. d: Specifies device where command will look for COMMAND.COM current default drive if absent. Specifies a directory on device d: root directory if absent. Name of the CTTY device. \DEV\CON if absent and command is permanent. The \DEV\ may be left off if AVAILDEV is TRUE (see sysinit doc). /C If present /C must be the last switch. This causes COMMAND to try to execute the string as if the user had typed it at the standard input. COMMAND executes this single command string and then exits. If the /P switch is present it is ignored (can't have a single command, permanent COMMAND). NOTE: ALL of the text on the command line after the /C is just passed on. It is not processed for more arguments, this is why /C must be last. /E:nnnn Set the environment size to nnnn (specified in decimal bytes). The environment size can be between 128 bytes and 32768 bytes. NOTE: This feature is only available in versions of MS-DOS starting with 3.20. GET_DPB UNDOCUMENTED SYSTEM CALL. THIS CALL MAY BE USED TO GET A POINTER TO THE PHYSICAL LOCATION OF THE DISK DEVICE DRIVER. CONSULT THE DBP STRUCTURE DOCUMENTED IN DOSSYM.ASM +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | C A V E A T P R O G R A M M E R | | | Name: * GET_DPB - get pointer to drive parameter block Assembler usage: MOV AH,GET_DPB INT 21h ; DS:BX has address of drive parameter block Description: Return pointer to default drive parameter block. Error returns: None. Assembler usage: MOV DL,DrvNUM MOV AH,32H INT 21h ; DS:BX has address of drive parameter block Description: Return pointer to drive parameter block for drive designated in DL (0=Default, A=1, B=2 ...) Error returns: AL = FF The drive given in DL is invalid. | | | C A V E A T P R O G R A M M E R | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ APPENDIX H This material was taken from the MS-DOS 3.10 Programmer's Reference Manual. It is intended be used with the MS-DOS 2.XX/3.XX Adaptation Guide. 7.1 INTRODUCTION This chapter describes recommended MS-DOS 3.1 programming procedures. By using these programming hints, you can ensure compatibility with future versions of MS-DOS. The hints are organized into the following categories: Interrupts System Calls Device Management Memory Management Process Management File and Directory Management Miscellaneous 7.2 INTERRUPTS Never explicitly issue Interrupt 22H (Terminate Process Exit Address). This should only be done by the DOS. To change the terminate address, use Function 35H (Get Interrupt Vector) to get the current address and save it, then use Function 25H (Set Interrupt Vector) to change the Interrupt 22H entry in the vector table to point to the new terminate address. PROGRAMMING HINTS Page 7-2 Use Interrupt 24H (Critical Error Handler Address) with care. The Interrupt 24H handler must preserve the ES register. Only system calls 01H-0CH can be made by an Interrupt 24H handler. Making any other calls will destroy the MS-DOS stack and prevent successful use of the Retry or Ignore options. The registers SS, SP, DS, BX, CX, and DX must be preserved when using the Retry or Ignore options. When an Interrupt 24H (Critical Error Handler Address) is received, always IRET back to MS-DOS with one of the standard responses. Programs that do not IRET from Interrupt 24H leave the system in an unpredictable state until a function call other than 01H-0CH is made. The Ignore option may leave data in internal system buffers that is incorrect or invalid. Avoid trapping Interrupt 23H (Control-C Handler Address) and Interrupt 24H (Critical Error Handler Address). Don't rely on trapping errors via Interrupt 24H as part of a copy protection scheme. These might not be included in future releases of the operating system. Interrupt 23H (Control-C Handler Address) must never be issued by a user program. Interrupt 23H must be issued only by MS-DOS. Save any registers your program uses before issuing Interrupt 25H (Absolute Disk Read) or Interrupt 26H (Absolute Disk Write). These interrupts destroy all registers except for the segment registers. Avoid writing or reading an interrupt vector directly to or from memory. Use Functions 25H and 35H (Set Interrupt Vector and Get Interrupt Vector) to set and get values in the interrupt table. PROGRAMMING HINTS Page 7-3 7.3 SYSTEM CALLS Use new system calls. Avoid using system calls that have been superseded by new calls unless a program must maintain backward ____ compatibility with pre-2.0 versions of MS-DOS. See Section 1.8, "Old System Calls," of this manual for a list of these new calls. Avoid using system calls 01H-0CH and 26H (Create New PSP). Use the new "tools" approach for reading and writing on standard input and output. Use Function 4B00H (Load and Execute Program) instead of 26H to execute a child process. Use file-sharing calls if more than one process is in effect. See "File Sharing," in Section 1.5.2, "File-Related Function Requests" in Chapter 1 for more information. Use networking calls where appropriate. Some forms of IOCTL can only be used with Microsoft Networks. See Section 1.6, "Microsoft Networks," in this manual for a list of these calls. When selecting a disk with Function 0EH (Select Disk), treat the value returned in AL with care. The value in AL specifies the maximum number of logical drives; it does not specify which drives are valid. 7.4 DEVICE MANAGEMENT Use installable device drivers. MS-DOS provides a modular device driver structure for the BIOS, allowing you to configure and install device drivers at boot time. Block device drivers transmit a block of data at a time, while character device drivers transmit a byte of data at a time. Examples of both types of device drivers are given in Chapter 2, "MS-DOS Device Drivers." PROGRAMMING HINTS Page 7-4 Use buffered I/O. The device drivers can handle streams of data up to 64K. When sending a large amount of output to the screen, you can send it with one system call. This will increase performance. Programs that use direct console I/O via Function 06H and 07H (Direct Console I/O and Direct Console Input) and that want to read Control-C as data should ensure that Control-C checking is off. The program should ensure that Control-C checking is off by using Function 33H (Control-C Check). Be compatible with international support. To provide support for international character sets, MS-DOS recognizes all possible byte values as significant characters in filenames and data streams. Pre-2.x versions ignored the high bit in the MS-DOS filename. 7.5 MEMORY MANAGEMENT Use memory management. MS-DOS keeps track of allocated memory by writing a memory control block at the beginning of each area of memory. Programs should use Functions 48H (Allocate Memory), 49H (Free Allocated Memory), and 4AH (Set Block) to release unneeded memory. This will allow for future compatibility. See Section 1.3, "Memory Management," for more information. Only use allocated memory. Don't directly access memory that was not provided as a result of a system call. Do not use fixed addressing, use only relative references. A program that uses memory that has not been allocated to it may destroy other memory control blocks or cause other applications to fail. PROGRAMMING HINTS Page 7-5 7.6 PROCESS MANAGEMENT Use the EXEC Function Call to load and execute programs. The EXEC Function (4B00H) is the preferred way to load programs and program overlays. Using the EXEC call instead of hard-coding information about how to load an .EXE file (or always assuming that your file is a .COM file) will isolate your program from changes in future releases of MS-DOS and .EXE file formats. Use Function 31H (Keep Process), instead of Interrupt 27H (Terminate But Stay Resident). Function 31H allows programs to terminate and stay resident that are greater than 64K. Programs should terminate using End Process (4CH). Programs that terminate by - a long jump to offset 0 in the PSP, - issuing an Interrupt 20H with CS:0 pointing at the PSP, - issuing an Interrupt 21H with AH=0, CS:0 pointing at the PSP, or - a long call to location 50H in the PSP with AH=0 must ensure that the CS register contains the segment address of the PSP. 7.7 FILE AND DIRECTORY MANAGEMENT Use the MS-DOS file management system. Using the MS-DOS file system will ensure program compatibility with future MS-DOS versions through compatible disk formats and consistent internal storage. This will ensure compatibility with future MS-DOS versions. Use file handles instead of FCBs. A handle is a 16-bit number that is returned by MS-DOS when a file is opened or created using Functions 3CH, 3DH, 5AH, or 5BH (Create Handle, Open Handle, Create Temporary File, or Create New File). The MS-DOS file-related function requests that use handles are listed in Table 1.5 in Chapter 1, "System Calls." These calls should be used instead of the old file-related functions that use FCBs (file control blocks). This is because a file operation can simply pass its handle rather than having to PROGRAMMING HINTS Page 7-6 maintain FCB information. If FCBs must be used, be sure the program closes them and does not move them around in memory. Close all files that have changed in length before issuing an Interrupt 20H (Program Terminate), Function 00H (Terminate Program), Function 4CH (End Process), or Function 0DH (Reset Disk). If a changed file is not closed, its length will not be recorded correctly in the directory. Close all files when they are no longer needed. Closing unneeded files will optimize performance in a networking environment. Only change disks if all files on the disk are closed. Information in internal system buffers may be written incorrectly to a changed disk. 7.7.1 Locking Files Programs should not rely on being denied access to a locked region. Determine the status of the region by attempting to lock it, and examine the error code. Programs should not close a file with a locked region or terminate with an open file that contains a locked region. The result is undefined. Programs that might be terminated by an Interrupt 23H or Interrupt 24H (Control-C Handler Address or Critical Error Handler Address) should trap these interrupts and unlock any locked regions before exiting. 7.8 MISCELLANEOUS Avoid timing dependencies. Various machines use CPUs of different speeds. Also, programs that rely upon the speed of the clock for timing will not be dependable in a networking environment. PROGRAMMING HINTS Page 7-7 Use the documented interface to the operating system. If either the hardware or media change, the operating system will be able to use the features without modification. Don't use the OEM (Original Equipment Manufacturer) -provided ROM support. Don't directly address the video memory. Don't use undocumented function calls, interrupts, or features. These items may change or not continue to exist in future versions of MS-DOS. Use of these features would make your program highly non-portable. Use the .EXE format rather than the .COM format. .EXE files are relocatable and .COM files are direct memory images that load at a specific place and have no room for additional control information to be placed in them. .EXE files have headers that can be expanded for compatibility with future versions of MS-DOS. Use the environment to pass information to applications. The environment allows a parent process to pass information to a child process. COMMAND.COM is usually the parent process to every application, so default drive and path information can easily be passed to the application. GLOSSARY OF MS-DOS TERMS Allocation Unit (See Cluster) Arena MS-DOS uses a software memory management scheme. Blocks in memory are either owned by processes or are free. An owned block has an ID number, which is the initial paragraph of the Program Segment GLOSSARY OF MS-DOS TERMS Prefix of a process in memory (your program). Each block has a size as well. When your process is in memory, there is a 16-byte arena block which identifies it and specifies how much memory is allocated. ASCIZ Any null (zero byte) terminated ASCII string. Cluster The storage unit that MS-DOS uses to allocate space for files on a disk. All files are allocated in multiples of clusters. A cluster must be a power of two sectors (i.e., 1, 2, 4, 8 ... ). This term is synonymous with allocation unit. Block device drivers perform I/O in sectors, not clusters. Cooked/Raw Mode Character devices have two modes that have significance when performing I/O via the Read Handle and Write Handle calls (Functions 3FH and 40H). These are "raw" and "cooked" mode. A device driver can be set to raw mode via the IOCTL Function Request 44H. Cooked mode input is buffered input with echoing to the screen (if console) and Control-C checking. Cooked mode input of a certain number of characters will return when the specified number of characters is returned or a carriage return is typed. Cooked mode output performs Control-C checking between characters. Raw mode I/O is very fast. When raw mode I/O of "n" characters is requested, MS-DOS passes the request directly to the indicated device driver. The device driver does not return to MS-DOS until the I/O has completed. Characters are written or read directly from the process buffer. No checking of any kind is performed. No characters have any significance, including Control-C. GLOSSARY OF MS-DOS TERMS For example, if the requesting program puts a device in raw mode and requests a write of 50,000 characters to the AUX device, the device driver will get a request from MS-DOS to write 50,000 characters from the buffer located at the DWORD transfer address. The driver will not return until the request has completed. In cooked mode, MS-DOS performs a Control-C check at the console after each single character write. This is an overhead of 50,000 Control-C checks. Environment The environment is a maximum of 32K data area which consists of ASCIZ strings of the form: AAAA=BBBBBBB. The end of the environment is marked by two consecutive nulls. The word at 2CH in the Program Segment Prefix points to the segment containing the start of a program's environment. New variables can be added to the environment by using the MS-DOS Set command. Since nulls have significance, the environment cannot be used for storing binary data. When a parent process (such as COMMAND.COM) executes a child process (any other program), the child is given a copy of the parent's environment. Parameters such as Prompt, which specifies the style of prompt used by COMMAND.COM, are stored in the environment. Application programs can use the environment to find overlays or special files which may not be located in the current directory. COMMAND.COM uses this technique to examine the elements of the Path looking for binaries and batch files. Of course the application program must be specifically coded to find the environment and parse it for variables. FATID Byte The FATID byte is the first byte of the File Allocation Table that starts at the sector immediately after the reserved sectors of the disk. The FATID byte was used by OEMs in MS-DOS 1.x for identification of disk media. This byte should be between F8H and FFH. To read MS-DOS 1.x disks, one must read this byte, determine which of the four predefined FATID bytes is present and return a pointer to the appropriate BPB. This method of GLOSSARY OF MS-DOS TERMS determining media is less general and less desirable than the BPB table method (see MEDIA ID Byte). File Handle In versions of MS-DOS that are 2.0 and higher, there is a system file table set up at boot time. By the time COMMAND.COM gets control, all of the character devices have been entered into the system file table. The first five handles are initialized as follows. HANDLE XENIX NAME DEFAULT SETTING 0 Standard Input CON 1 Standard Output CON 2 Standard Error CON 3 Standard AUX AUX 4 Standard PRN PRN As new files are opened via XENIX-compatible calls, they are assigned the first available numbers. When COMMAND.COM executes a program, the child process inherits all of the handles that COMMAND.COM has open. Typing prog < infyle > outfyle on the command line means that you want PROG to read its input from INFYLE and write its output to OUTFYLE instead of to console out. COMMAND.COM will close handle 0 and open INFYLE; it will DUP handle 0. It will then close handle 1, standard out, and open OUTFYLE (which is assigned to standard out). COMMAND will exec PROG, which inherits this environment. When PROG reads from standard in, or writes to standard out, it reads from and writes to INFYLE and OUTFYLE, respectively. If a child is executed, it inherits the files of its parent. The converse is not true. When a child process which opens AUX as standard in and PRN as standard out returns, the parent does not ___ inherit the files of its child. GLOSSARY OF MS-DOS TERMS MEDIA ID Byte The MEDIA ID byte is the byte in the Bios Parameter Block (BPB) located at offset 0AH. The MEDIA ID byte may have any value between 0 and 0FFH. It may or may not have the same value as the FATID byte. The major significance of the MEDIA ID byte is that there be a one-to-one relationship between unique MEDIA ID bytes and disk formats. For disk compatibility with other OEMs as well as with future releases of MS-DOS, Microsoft recommends that the BPB table be located at offset 0BH in the first reserved (boot) sector. OEMs may register their media byte/format combinations with OEM Customer Support. The BPB technique of determining disk format is much more general than the limited FATID byte method and is the preferred method. The significance of the media byte and FATID byte depends on whether you have decided to make your block device driver IBM format-compatible. You must indicate this by setting bit 13 in the device driver header. This will alter the way MS-DOS performs the GET BPB device call. With the NON FATID bit set, you can support various media, including IBM format media. If the device driver is IBM-format compatible, use FATID bytes to determine the media in the drive. The correspondence between FATID bytes and various media is defined in the MS-DOS Programmer's ______ ____________ Reference Manual. _________ ______ If your system is not IBM Format-compatible, you are given a pointer to a one-sector scratch buffer when your block device gets called by MS-DOS to do a BUILD BPB. Follow these steps: 1. Read the boot sector of the disk into that buffer and check the first byte. If it is an E9H, it is the first byte of a 3-byte JMP and there is a BIOS Parameter Block table in the boot sector. Alternately, EBH may be the first byte. This is also a 3-byte JMP (actually, a 2-byte JMP followed by a NOP). GLOSSARY OF MS-DOS TERMS 2. Return a pointer to the BPB. Set the status word and return. If the first byte of the boot sector is not an E9H, then there is not a BPB table in the boot sector. You can assume that the disk is an IBM format disk and the FAT begins with the second sector of the disk. Read the FAT into the scratch buffer and check the first byte. Determine which one of the four defined FATID bytes it is, and return a pointer to the appropriate BPB. Refer to the MS-DOS Programmer's Reference ______ ____________ _________ Manual for a list of valid FATID bytes. Any ______ other media should be defined in the boot sector and should use a FATID byte of FFH. Paragraph Any location in the memory of the 8086 which has an address that is a multiple of 16 (i.e., 0, 16, 32).