mirror of
				https://github.com/microsoft/MS-DOS.git
				synced 2025-10-31 02:37:27 +00:00 
			
		
		
		
	MS-DOS v2.0 Release
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								v2.0/bin/ANSI.DOC
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2.0/bin/ANSI.DOC
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								v2.0/bin/CHKDSK.COM
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2.0/bin/CHKDSK.COM
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								v2.0/bin/COMMAND.COM
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2.0/bin/COMMAND.COM
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								v2.0/bin/CONFIG.DOC
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2.0/bin/CONFIG.DOC
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								v2.0/bin/CREF.EXE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2.0/bin/CREF.EXE
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								v2.0/bin/DEBUG.COM
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								v2.0/bin/DEBUG.COM
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										802
									
								
								v2.0/bin/DEVDRIV.DOC
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										802
									
								
								v2.0/bin/DEVDRIV.DOC
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,802 @@ | ||||
|                   MS-DOS 2.0 Device Drivers | ||||
|  | ||||
| INTRODUCTION | ||||
|  | ||||
|     In the  past,  DOS-device  driver  (BIOS for those who are | ||||
| familiar with  CP/M)  communication  has  been  mediated  with | ||||
| registers and   a  fixed-address  jump-table.   This  approach | ||||
| has suffered heavily  from  the  following  two  observations: | ||||
|  | ||||
|     o   The old jump-table ideas of  the  past  are  fixed  in | ||||
|         scope and allow no extensibility. | ||||
|  | ||||
|     o   The past  device  driver  interfaces have been written | ||||
|         without regard for the true  power  of  the  hardware. | ||||
|         When   a   multitasking  system  or  interrupt  driven | ||||
|         hardware is installed  a  new  BIOS  must  be  written | ||||
|         largely from scratch. | ||||
|  | ||||
|     In MSDOS  2.0, the DOS-device driver interface has changed | ||||
| from the old jump-table style  to  one  in  which  the  device | ||||
| drivers  are  linked  together  in  a  list.   This allows new | ||||
| drivers for  optional  hardware  to  be  installed  (and  even | ||||
| written) in  the  field  by other vendors or the user himself. | ||||
| This flexibility is one of the major new  features  of  MS-DOS | ||||
| 2.0. | ||||
|  | ||||
|     Each driver  in  the  chain  defines two entry points; the | ||||
| strategy routine and  the  interrupt  routine.   The  2.0  DOS | ||||
| does not  really make use of two entry points (it simply calls | ||||
| strategy, then immediately calls interrupt).  This dual  entry | ||||
| point scheme  is  designed  to facilitate future multi-tasking | ||||
| versions of MS-DOS.  In multi-tasking  environments  I/O  must | ||||
| be asynchronous,  to  accomplish  this  the  strategy  routine | ||||
| will be called to queue  (internally)  a  request  and  return | ||||
| quickly.  It  is  then  the  responsibility  of  the interrupt | ||||
| routine to perform the actual I/O at interrupt time by picking | ||||
| requests  off  the  internal  queue  (set  up  by the strategy | ||||
| routine), and process  them.   When  a  request  is  complete, | ||||
| it is  flagged  as  "done"  by the interrupt routine.  The DOS | ||||
| periodically scans the  list  of  requests  looking  for  ones | ||||
| flagged as  done,  and  "wakes up" the process waiting for the | ||||
| completion of the request. | ||||
|  | ||||
|     In order for requests to be  queued  as  above  it  is  no | ||||
| longer sufficient  to pass I/O information in registers, since | ||||
| many requests may be  pending  at  any  one  time.   Therefore | ||||
| the new  device  interface uses data "packets" to pass request | ||||
| information.  A device is called with a pointer to  a  packet, | ||||
| this packet  is  linked  into  a  global  chain of all pending | ||||
| I/O requests maintained by the DOS.   The  device  then  links | ||||
| the packet  into  its  own  local  chain  of requests for this | ||||
| particular  device.   The  device  interrupt   routine   picks | ||||
| requests of  the  local  chain  for processing.  The DOS scans | ||||
| the  global  chain  looking  for  completed  requests.   These | ||||
| packets are  composed  of  two  pieces,  a  static piece which | ||||
| has the same  format  for  all  requests  (called  the  static | ||||
| request header),  which  is  followed  by information specific | ||||
| to the request.  Thus packets have a variable size and format. | ||||
|  | ||||
|     At this points it should be  emphasized  that  MS-DOS  2.0 | ||||
| does not  implement most of these features, as future versions | ||||
| will.  There is no global or local queue.   Only  one  request | ||||
| is pending at any one time, and the DOS waits for this current | ||||
| request to be completed.  For 2.0 it  is  sufficient  for  the | ||||
| strategy routine  to  simply  store  the address of the packet | ||||
| at a fixed location, and for the  interrupt  routine  to  then | ||||
| process  this  packet  by  doing  the  request  and returning. | ||||
| Remember:  the DOS just calls the strategy  routine  and  then | ||||
| immediately calls  the  interrupt  routine, it is assumed that | ||||
| the request is completed when the interrupt  routine  returns. | ||||
| This additional  functionality  is  defined  at  this  time so | ||||
| that people will be  aware  and  thinking  about  the  future. | ||||
|  | ||||
|  | ||||
| FORMAT OF A DEVICE DRIVER | ||||
|  | ||||
|     A device  driver  is  simply  a  relocatable  memory image | ||||
| with all of the code in  it  to  implement  the  device  (like | ||||
| a .COM  file,  but  not ORGed at 100 Hex).  In addition it has | ||||
| a special header at the front of it  which  identifies  it  as | ||||
| a device,  defines  the  strategy  and interrupt entry points, | ||||
| and defines various  attributes.   It  should  also  be  noted | ||||
| that there are two basic types of devices. | ||||
|  | ||||
|     The first  is  character devices.  These are devices which | ||||
| are designed to do character  I/O  in  a  serial  manner  like | ||||
| CON, AUX,  and  PRN.   These devices are named (ie.  CON, AUX, | ||||
| CLOCK, etc.), and users may open channels  (FCBs)  to  do  I/O | ||||
| to them. | ||||
|  | ||||
|     The second  class  of  devices  is  block  devices.  These | ||||
| devices are the "disk drives"  on  the  system,  they  can  do | ||||
| random I/O  in  pieces  called  blocks  (usually  the physical | ||||
| sector size) and  hence  the  name.   These  devices  are  not | ||||
| "named" as  the  character  devices  are, and therefore cannot | ||||
| be "opened" directly.   Instead  they  are  "mapped"  via  the | ||||
| drive letters (A,B,C, etc.). | ||||
|  | ||||
|     Block devices  also  have  units.  In other words a single | ||||
| driver may be responsible for one or more  disk  drives.   For | ||||
| instance block device driver ALPHA (please note that we cannot | ||||
| actually  refer  to  block  devices  by  a  name!)    may   be | ||||
| responsible for  drives  A,B,C  and  D, this simply means that | ||||
| it has four units (0-3) defined and therefore  takes  up  four | ||||
| drive letters.   Which units correspond to which drive letters | ||||
| is determined by the position  of  the  driver  in  the  chain | ||||
| of all  drivers:   if  driver  ALPHA is the first block driver | ||||
| in the device chain, and it defines 4 units (0-3),  then  they | ||||
| will be  A,B,C  and  D.   If  BETA  is the second block driver | ||||
| and defines three units (0-2),  then  they  will  be  E,F  and | ||||
| G and  so  on.   MS-DOS  2.0 is not limited to 16 block device | ||||
| units, as  previous  versions  were.   The  theoretical  limit | ||||
| is 63  (2^6  -  1),  but  it should be noted that after 26 the | ||||
| drive letters get a little strange (like ] \  and  ^).   NOTE: | ||||
| Character devices  cannot  define multiple units (this because | ||||
| they have only one name). | ||||
|  | ||||
|  | ||||
| Here is what that special device header looks like: | ||||
|  | ||||
|            +--------------------------------------+ | ||||
|            | DWORD Pointer to next device         | | ||||
|            | (Must be set to -1)                  | | ||||
|            +--------------------------------------+ | ||||
|            | WORD Attributes                      | | ||||
|            |  Bit 15 = 1 if char device 0 if blk  | | ||||
|            |  if bit 15 is 1                      | | ||||
|            |      Bit 0 = 1 if Current sti device | | ||||
|            |      Bit 1 = 1 if Current sto output | | ||||
|            |      Bit 2 = 1 if Current NUL device | | ||||
|            |      Bit 3 = 1 if Current CLOCK dev  | | ||||
|            |      Bit 4 = 1 if SPECIAL            | | ||||
|            |  Bit 14 is the IOCTL bit (see below) | | ||||
|            |  Bit 13 is the NON IBM FORMAT bit    | | ||||
|            +--------------------------------------+ | ||||
|            | WORD Pointer to Device strategy      | | ||||
|            |      entry point                     | | ||||
|            +--------------------------------------+ | ||||
|            | WORD Pointer to Device interrupt     | | ||||
|            |      entry point                     | | ||||
|            +--------------------------------------+ | ||||
|            | 8-BYTE character device name field   | | ||||
|            | Character devices set a device name  | | ||||
|            | For block devices the first byte is  | | ||||
|            | The number of units                  | | ||||
|            +--------------------------------------+ | ||||
|  | ||||
|     Note that the device entry points are  words.   They  must | ||||
| be offsets  from  the  same  segment  number  used to point to | ||||
| this table.  Ie.  if XXX.YYY  points  to  the  start  of  this | ||||
| table, then  XXX.strategy  and  XXX.interrupt  are  the  entry | ||||
| points. | ||||
|  | ||||
|     A word about the Attribute  field.   This  field  is  used | ||||
| most importantly  to  tell  the  system whether this device is | ||||
| a block or character device (bit  15).   Most  of  other  bits | ||||
| are used  to  give  selected character devices certain special | ||||
| treatment (NOTE: these bits mean nothing on a  block  device). | ||||
| Let's say  a  user  has  a new device driver which he wants to | ||||
| be the standard input and  output.   Besides  just  installing | ||||
| the driver  he  needs  to  tell  SYSINIT (and the DOS) that he | ||||
| wishes his new driver to override  the  current  sti  and  sto | ||||
| (the "CON"  device).   This  is  accomplished  by  setting the | ||||
| attributes to the desired characteristics,  so  he  would  set | ||||
| Bits 0  and 1 to 1 (note that they are separate!!).  Similarly | ||||
| a  new  CLOCK  device  could  be  installed  by  setting  that | ||||
| attribute, see  the  section  at  the end on the CLOCK device. | ||||
| NOTE: that although there  is  a  NUL  device  attribute,  the | ||||
| NUL device  cannot  be  re-assigned.   This  attribute  exists | ||||
| for the DOS so that it can tell if the  NUL  device  is  being | ||||
| used. | ||||
|  | ||||
|     The NON  IBM  FORMAT  bit  applies  only  to block devices | ||||
| and effects the operation of the  get  BPB  device  call  (see | ||||
| below). | ||||
|  | ||||
|     The other  bit  of  interest  is  the  IOCTL bit which has | ||||
| meaning on character or block devices.   This  bit  tells  the | ||||
| DOS whether  this  device  can handle control strings (via the | ||||
| IOCTL system call). | ||||
|  | ||||
|     If a driver cannot  process  control  strings,  it  should | ||||
| initially set  this  bit  to  0.  This tells the DOS to return | ||||
| an error if an attempt is made  (via  IOCTL  system  call)  to | ||||
| send or  receive  control  strings  to  this device.  A device | ||||
| which can process control  strings  should  initialize  it  to | ||||
| 1.  For  drivers  of  this  type,  the  DOS will make calls to | ||||
| the IOCTL INPUT  and  OUTPUT  device  functions  to  send  and | ||||
| receive   IOCTL   strings   (see  IOCTL  in  the  SYSTEM-CALLS | ||||
| document). | ||||
|  | ||||
|     The IOCTL functions allow data to  be  sent  and  received | ||||
| by the  device  itself for its own use (to set baud rate, stop | ||||
| bits, form length etc., etc.), instead of  passing  data  over | ||||
| the  device  channel  as  a  normal  read  or write does.  The | ||||
| interpretation of the passed information is up to the  device, | ||||
| but it MUST NOT simply be treated as a normal I/O. | ||||
|  | ||||
|     The SPECIAL  bit  applies  only  to  character drivers and | ||||
| more particularly to  CON  drivers.   The  new  2.0  interface | ||||
| is a  much  more  general  and  consistent  interface than the | ||||
| old 1.25 DOS interface.  It allows for a number of  additional | ||||
| features of  2.0.   It  is  also slower than 1.25 if old style | ||||
| "single byte" system calls are made.  To make  most  efficient | ||||
| use of  the  interface  all  applications  should  block their | ||||
| I/O as much as possible.  This  means  make  one  XENIX  style | ||||
| system call  to  output  X  bytes  rather  than X system calls | ||||
| to output one byte each.  Also putting  a  device  channel  in | ||||
| RAW   mode  (see  IOCTL)  provides  a  means  of  putting  out | ||||
| characters even FASTER  than  1.25.   To  help  alleviate  the | ||||
| CON output  speed  problem  for  older  programs which use the | ||||
| 1 - 12 system calls  to  output  large  amounts  of  data  the | ||||
| SPECIAL bit  has  been implemented.  If this bit is 1 it means | ||||
| the device is the  CON  output  device,  and  has  implemented | ||||
| an interrupt  29  Hex  handler,  where  the  29 Hex handler is | ||||
| defined as follows: | ||||
|  | ||||
|         Interrupt 29h handlers | ||||
|  | ||||
|         Input: | ||||
|                 Character in AL | ||||
|  | ||||
|         Function: | ||||
|                 output the character in al to the user | ||||
|                 screen. | ||||
|         Output: | ||||
|                 None | ||||
|         Registers: | ||||
|                 all registers except bx must be preserved. | ||||
|                 No registers except for al have a known or | ||||
|                 consistent value. | ||||
|  | ||||
|     If a  character  device  implements  the  SPECIAL  bit, it | ||||
| is the responsibility of the  driver  to  install  an  address | ||||
| at the  correct  location in the interrupt table for interrupt | ||||
| 29 Hex as part of  its  INIT  code.   IMPLICATION:  There  can | ||||
| be only  one  device  driver  with  the SPECIAL bit set in the | ||||
| system.  There is no check to insure this state. | ||||
|  | ||||
| WARNING: THIS FEATURE WILL NOT BE SUPPORTED IN FUTURE VERSIONS | ||||
|     OF THE  OPERATING  SYSTEM.   IMPLICATION:  Any application | ||||
|     (not device driver)  which  uses  INT  29H  directly  will | ||||
|     not work on future versions, YOU HAVE BEEN WARNED. | ||||
|  | ||||
|     In  order  to  "make"  a  device  driver  that SYSINIT can | ||||
| install, a memory image or .EXE  (non-IBM  only)  format  file | ||||
| must be  created  with  the  above  header  at the start.  The | ||||
| link field should be  initialized  to  -1  (SYSINIT  fills  it | ||||
| in).   The  attribute  field  and  entry  points  must  be set | ||||
| correctly, and if the device is a character device,  the  name | ||||
| field must  be  filled  in  with  the  name (if a block device | ||||
| SYSINIT will fill in  the  correct  unit  count).   This  name | ||||
| can be  any  8  character  "legal" file name.  In fact SYSINIT | ||||
| always installs character devices at the start of  the  device | ||||
| list, so  if  you  want  to  install  a new CON device all you | ||||
| have to do is name it "CON".  The new  one  is  ahead  of  the | ||||
| old one  in  the  list  and  thus  preempts the old one as the | ||||
| search for devices stops on  the  first  match.   Be  sure  to | ||||
| set the sti and sto bits on a new CON device! | ||||
|  | ||||
| NOTE:  Since  SYSINIT  may  install  the  driver anywhere, you | ||||
|     must be very careful about  FAR  memory  references.   You | ||||
|     should NOT  expect  that  your  driver will go in the same | ||||
|     place every time (The default BIOS  drivers  are  exempted | ||||
|     from this of course). | ||||
|  | ||||
|  | ||||
| INSTALLATION OF DEVICE DRIVERS | ||||
|  | ||||
|     Unlike past versions MS-DOS 2.0 allows new device  drivers | ||||
| to   be   installed   dynamically   at  boot  time.   This  is | ||||
| accomplished by the new SYSINIT module supplied by  Microsoft, | ||||
| which reads  and  processes  the CONFIG.SYS file.  This module | ||||
| is linked together with the OEM  default  BIOS  in  a  similar | ||||
| manner to the way FORMAT is built. | ||||
|  | ||||
|     One of  the  functions  defined  for  each device is INIT. | ||||
| This routine is called once  when  the  device  is  installed, | ||||
| and never  again.  The only thing returned by the init routine | ||||
| is a location (DS:DX) which is a pointer  to  the  first  free | ||||
| byte of  memory  after  the  device  driver, (like a terminate | ||||
| and stay resident).  This pointer method can be used to "throw | ||||
| away" initialization  code  that  is  only needed once, saving | ||||
| on space. | ||||
|  | ||||
|     Block devices are installed the same way and  also  return | ||||
| a first  free  byte  pointer  as above, additional information | ||||
| is also returned: | ||||
|  | ||||
|     o   The number  of  units  is  returned,  this  determines | ||||
|         logical device  names.  If the current maximum logical | ||||
|         device letter is F at the time of  the  install  call, | ||||
|         and the init routine returns 4 as the number of units, | ||||
|         then they will have logical  names  G,  H,  I  and  J. | ||||
|         This mapping  is  determined  by  by  the  position of | ||||
|         the driver in the device list and the number of  units | ||||
|         on the  device (stored in the first byte of the device | ||||
|         name field). | ||||
|  | ||||
|     o   A pointer to a  BPB  (Bios  Parameter  Block)  pointer | ||||
|         array is  also  returned.   This  will  be  similar to | ||||
|         the INIT table used in  previous  versions,  but  will | ||||
|         have more  information  in  it.   There  is  one table | ||||
|         for each unit defined.   These  blocks  will  be  used | ||||
|         to build  a  DPB  (Drive  Parameter Block) for each of | ||||
|         the units.  The pointer passed to  the  DOS  from  the | ||||
|         driver points  to  an array of n word pointers to BPBs | ||||
|         where n is the  number  of  units  defined.   In  this | ||||
|         way if  all  units  are  the same, all of the pointers | ||||
|         can point to the same BPB, saving space.   NOTE:  this | ||||
|         array must  be  protected  (below the free pointer set | ||||
|         by the return) since the DPB will  be  built  starting | ||||
|         at the  byte  pointed  to  by  the  free pointer.  The | ||||
|         sector size defined must be  less  than  or  equal  to | ||||
|         the maximum  sector  size defined at default BIOS init | ||||
|         time.  If it isn't the install  will  fail.   One  new | ||||
|         piece of DPB info set from this table will be a "media | ||||
|         descriptor byte".  This  byte  means  nothing  to  the | ||||
|         DOS, but  is  passed to devices so that they know what | ||||
|         form of a  DPB  the  DOS  is  currently  using  for  a | ||||
|         particular Drive-Unit. | ||||
|  | ||||
|     Block devices  may  take  several  approaches; they may be | ||||
| dumb or smart.   A  dumb  device  would  define  a  unit  (and | ||||
| therefore a  DPB)  for  each possible media drive combination. | ||||
| Unit 0 = drive 0 single side, unit 1 = drive  0  double  side, | ||||
| etc.  For  this  approach  media  descriptor  bytes would mean | ||||
| nothing.  A smart device would allow multiple media per  unit, | ||||
| in this  case the BPB table returned at init must define space | ||||
| large  enough  to  accommodate  the  largest  possible   media | ||||
| supported.  Smart  drivers  will  use the "media byte" to pass | ||||
| around info about what media is currently in  a  unit.   NOTE: | ||||
| If the  DPB  is  a  "hybrid"  made  to get the right sizes, it | ||||
| should give an invalid "media byte" back to the DOS. | ||||
|  | ||||
|     The BOOT  (default  BIOS)  drivers  are  installed  pretty | ||||
| much as  above.   The preset device list is scanned.  If block | ||||
| drivers are encountered they  are  installed  as  above  (with | ||||
| the exception  that  the  break is not moved since the drivers | ||||
| are already resident in the  BIOS).   Note  that  the  logical | ||||
| drive letters  are  assigned  in  list  order, thus the driver | ||||
| which is to have logical A must  be  the  first  unit  of  the | ||||
| first  block  device  in  the  list.   The  order of character | ||||
| devices is also important.  There must be at least 4 character | ||||
| devices defined  at  boot which must be the first four devices | ||||
| (of either  type),  the  first  will  become  standard  input, | ||||
| standard output,  and  standard error output.  The second will | ||||
| become standard auxiliary input and  output,  the  third  will | ||||
| become standard  list  output,  and  the forth will become the | ||||
| date/time (CLOCK) device.  Thus  the  BIOS  device  list  must | ||||
| look like this: | ||||
|  | ||||
| ->CON->AUX->PRN->CLOCK->any other block or character devices | ||||
|  | ||||
| THE DRIVER | ||||
|  | ||||
|     A device driver will define the following functions: | ||||
|  | ||||
|   Command   Function | ||||
|    Code | ||||
|  | ||||
|      0      INIT | ||||
|      1      MEDIA CHECK (Block only, NOP for character) | ||||
|      2      BUILD BPB      "    "     "    "   " | ||||
|      3      IOCTL INPUT (Only called if device has IOCTL) | ||||
|      4      INPUT (read) | ||||
|      5      NON-DESTRUCTIVE INPUT NO WAIT (Char devs only) | ||||
|      6      INPUT STATUS                    "     "    " | ||||
|      7      INPUT FLUSH                     "     "    " | ||||
|      8      OUTPUT (write) | ||||
|      9      OUTPUT (Write) with verify | ||||
|     10      OUTPUT STATUS                   "     "    " | ||||
|     11      OUTPUT FLUSH                    "     "    " | ||||
|     12      IOCTL OUTPUT (Only called if device has IOCTL) | ||||
|  | ||||
|     As mentioned before, the first entry point is the strategy | ||||
| routine which  is called with a pointer to a data block.  This | ||||
| call does not perform the request, all it  does  is  queue  it | ||||
| (save the  data  block  pointer).   The second interrupt entry | ||||
| point is called immediately  after  the  strategy  call.   The | ||||
| "interrupt" routine  is called with no parameters, its primary | ||||
| function is to perform  the  operation  based  on  the  queued | ||||
| data block and set up any returns. | ||||
|  | ||||
|     The "BUILD  BPB"  and  "MEDIA  CHECK"  are the interesting | ||||
| new ones, these are explained by  examining  the  sequence  of | ||||
| events in the DOS which occurs when a drive access call (other | ||||
| than read or write) is made: | ||||
|  | ||||
|         I.  Turn drive letter  into  DPB  pointer  by  looking | ||||
|             for DPB with correct driver-unit number. | ||||
|  | ||||
|         II. Call device  driver  and  request  media check for | ||||
|             Drive-Unit.   DOS   passes   its   current   Media | ||||
|             descriptor byte (from DPB).  Call returns: | ||||
|  | ||||
|                 Media Not Changed | ||||
|                 Media Changed | ||||
|                 Not Sure | ||||
|                 Error | ||||
|  | ||||
|             Error - If an error occurs the error  code  should | ||||
|                 be set accordingly. | ||||
|  | ||||
|             Media Not  changed  -  Current  DPB and media byte | ||||
|                 are OK, done. | ||||
|  | ||||
|             Media Changed - Current DPB and media  are  wrong, | ||||
|                 invalidate any  buffers  for  this  unit,  and | ||||
|                 goto III. | ||||
|  | ||||
|             Not Sure - If there are  dirty  buffers  for  this | ||||
|                 unit, assume  DPB  and  media  byte are OK and | ||||
|                 done.  If nothing dirty, assume media changed, | ||||
|                 invalidate any  buffers  for  unit,  and  goto | ||||
|                 III. | ||||
|  | ||||
|             NOTE:  If a hybrid  DPB  was  built  at  init  and | ||||
|                 an invalid  Media  byte  was  set,  the driver | ||||
|                 should return media changed when this  invalid | ||||
|                 media byte is encountered. | ||||
|  | ||||
|         III. Call device  driver  to build BPB with media byte | ||||
|             and buffer. | ||||
|  | ||||
|     What the  driver  must  do  at  step  III is determine the | ||||
| correct media that is currently in  the  unit,  and  return  a | ||||
| pointer to  a  BPB table (same as for the install call).  This | ||||
| table will be used as at init  to  build  a  correct  DPB  for | ||||
| the unit  If the determined media descriptor byte in the table | ||||
| turns out to be the same as the one passed in,  then  the  DOS | ||||
| will not  build  a new table, but rather just use the old one. | ||||
| Therefore in this case the driver doesn't  have  to  correctly | ||||
| fill in the other entries if desired. | ||||
|  | ||||
|     The build  BPB  call  also  gets a pointer to a one sector | ||||
| buffer.  What this buffer contains is determined  by  the  NON | ||||
| IBM FORMAT  bit  in  the  attribute field.  If the bit is zero | ||||
| (device is IBM format compatible)  then  the  buffer  contains | ||||
| the first  sector  of  the  first  FAT,  in particular the FAT | ||||
| ID byte is the first byte  of  this  buffer.   NOTE:  It  must | ||||
| be true  that  the  BPB is the same, as far as location of the | ||||
| FAT is concerned, for all possible  media.   This  is  because | ||||
| this first  FAT  sector  must  be  read  BEFORE the actual BPB | ||||
| is returned.  If the NON  IBM  FORMAT  bit  is  set  then  the | ||||
| pointer points  to  one  sector  of scratch space which may be | ||||
| used for anything. | ||||
|  | ||||
| CALL FORMAT | ||||
|  | ||||
|     When the  DOS calls a device driver to perform a finction, | ||||
| it passes a  structure  (Drive  Request  Structure)  in  ES:BX | ||||
| to perform  operations  and  does  a long call to the driver's | ||||
| strategy entry point.  This structure is a fixed length header | ||||
| (Static Request  Header)  followed  by  data  pertinent to the | ||||
| operation  being  performed.   NOTE:   It   is   the   drivers | ||||
| responsibility to preserve machine state. | ||||
|  | ||||
| STATIC REQUEST HEADER -> | ||||
|                +-----------------------------+ | ||||
|                | BYTE length of record       | | ||||
|                |  Length in bytes of this    | | ||||
|                |  Drive Request Structure    | | ||||
|                +-----------------------------+ | ||||
|                | BYTE unit code              | | ||||
|                |  The subunit the operation  | | ||||
|                |  is for (minor device)      | | ||||
|                |  (no meaning on character   | | ||||
|                |   devices)                  | | ||||
|                +-----------------------------+ | ||||
|                | BYTE command code           | | ||||
|                +-----------------------------+ | ||||
|                | WORD Status                 | | ||||
|                +-----------------------------+ | ||||
|                | 8 bytes reserved here for   | | ||||
|                | two DWORD links. One will   | | ||||
|                | be a link for the DOS queue | | ||||
|                | The other for the device    | | ||||
|                | queue                       | | ||||
|                +-----------------------------+ | ||||
|  | ||||
| STATUS WORD | ||||
|  | ||||
|       15  14 13 12 11 10  9   8   7  6  5  4  3  2  1  0 | ||||
|     +---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+ | ||||
|     | E |               | B | D |                       | | ||||
|     | R |   RESERVED    | U | O | ERROR CODE (bit 15 on)| | ||||
|     | R |               | I | N |                       | | ||||
|     +---+---+--+--+--+--+---+---+--+--+--+--+--+--+--+--+ | ||||
|  | ||||
|     The status  word is zero on entry and is set by the driver | ||||
| interrupt routine on return. | ||||
|  | ||||
|     Bit 8 is the done bit, it means the operation is complete. | ||||
| For the  moment  the Driver just sets it to one when it exits, | ||||
| in the future this will be set by  the  interrupt  routine  to | ||||
| tell the DOS the operation is complete. | ||||
|  | ||||
|     Bit 15 is the error bit, if it  is  set  then  the  low  8 | ||||
| bits indicate the error: | ||||
|  | ||||
|            0 Write Protect violation | ||||
|     (NEW)  1 Unknown Unit | ||||
|            2 Drive not ready | ||||
|     (NEW)  3 Unknown command | ||||
|            4 CRC error | ||||
|     (NEW)  5 Bad Drive Request Structure length | ||||
|            6 Seek error | ||||
|     (NEW)  7 Unknown media | ||||
|            8 Sector not found | ||||
|     (NEW)  9 Printer out of paper | ||||
|            A Write Fault | ||||
|     (NEW)  B Read Fault | ||||
|            C General Failure | ||||
|  | ||||
| Bit 9 is the busy bit which is set only by status  calls  (see | ||||
| STATUS CALL below). | ||||
|  | ||||
|  | ||||
|    Here is the data block format for each function: | ||||
|  | ||||
| READ or WRITE - ES:BX (Including IOCTL) -> | ||||
|             +------------------------------------+ | ||||
|             | 13-BYTE  Static Request Header     | | ||||
|             +------------------------------------+ | ||||
|             | BYTE Media descriptor  from DPB    | | ||||
|             +------------------------------------+ | ||||
|             | DWORD transfer address             | | ||||
|             +------------------------------------+ | ||||
|             | WORD byte/sector Count             | | ||||
|          ---+------------------------------------+--- | ||||
|             | WORD starting sector number        | | ||||
|             |  (ignored on Char Devs)            | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|     In addition to setting the status word,  the  driver  must | ||||
| set the  Sector  count  to  the  actual  number of sectors (or | ||||
| bytes) transferred.  NOTE: No  error  check  is  performed  on | ||||
| an IOCTL I/O call, driver MUST correctly set the return sector | ||||
| (byte) count  to  the  actual  number  of  bytes  transferred, | ||||
| however. | ||||
|  | ||||
| NOTE: THE FOLLOWING APPLIES TO BLOCK DEVICE DRIVERS. | ||||
|  | ||||
|     Under certain  circumstances  the  BIOS  may  be  asked to | ||||
| do a write operation of 64K bytes which seems to  be  a  "wrap | ||||
| around" of  the transfer address in the BIOS I/O packet.  This | ||||
| arises due to an optimization  added  to  the  write  code  in | ||||
| MS-DOS.  It will only manifest on user WRITEs which are within | ||||
| a sector size of 64K bytes on files which are  "growing"  past | ||||
| the current  EOF.   IT  IS  ALLOWABLE  FOR  THE BIOS TO IGNORE | ||||
| THE BALANCE OF  THE  WRITE  WHICH  "WRAPS  AROUND"  IF  IT  SO | ||||
| CHOOSES.   For  instance  a  WRITE  of  10000H  bytes worth of | ||||
| sectors with a transfer address  of  XXX:1  could  ignore  the | ||||
| last two bytes (remember that a user program can never request | ||||
| an I/O of more than FFFFH bytes and cannot wrap  around  (even | ||||
| to 0)  in  his  transfer segment, so in this case the last two | ||||
| bytes can be ignored). | ||||
|  | ||||
|  | ||||
| NON DESRUCTIVE READ NO WAIT - ES:BX -> | ||||
|             +------------------------------------+ | ||||
|             | 13-BYTE Static Request Header      | | ||||
|             +------------------------------------+ | ||||
|             | BYTE read from device              | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|     This call is analogous to the console  input  status  call | ||||
| on MS-DOS  1.25.   If  the  character  device returns Busy bit | ||||
| = 0 (characters in  buffer),  then  the  next  character  that | ||||
| would be  read  is  returned.   This  character is NOT removed | ||||
| from the input buffer (hence the term Non  Destructive  Read). | ||||
| In essence  this  call  allows the DOS to look ahead one input | ||||
| character. | ||||
|  | ||||
|  | ||||
| MEDIA CHECK - ES:BX -> | ||||
|             +------------------------------------+ | ||||
|             | 13-BYTE  Static Request Header     | | ||||
|             +------------------------------------+ | ||||
|             | BYTE Media Descriptor from DPB     | | ||||
|             +------------------------------------+ | ||||
|             | BYTE returned                      | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|     In addition to setting status word, driver  must  set  the | ||||
| return byte. | ||||
|  | ||||
|     Return Byte : | ||||
|         -1 Media has been changed | ||||
|          0 Don't know if media has been changed | ||||
|          1 Media has not been changed | ||||
|  | ||||
|     If the driver can return -1 or 1 (by  having  a  door-lock | ||||
| or other  interlock  mechanism)  the  performance of MSDOS 2.0 | ||||
| is enhanced as the DOS  need  not  reread  the  FAT  for  each | ||||
| directory access. | ||||
|  | ||||
|  | ||||
| BUILD BPB - ES:BX -> | ||||
|             +------------------------------------+ | ||||
|             | 13-BYTE Static Request Header      | | ||||
|             +------------------------------------+ | ||||
|             | BYTE Media Descriptor from DPB     | | ||||
|             +------------------------------------+ | ||||
|             | DWORD Transfer Address             | | ||||
|             | (points to one sectors worth of    | | ||||
|             |  scratch space or first sector     | | ||||
|             |  of FAT depending on the value     | | ||||
|             |  of the NON IBM FORMAT bit)        | | ||||
|             +------------------------------------+ | ||||
|             | DWORD Pointer to BPB               | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|     If the NON IBM FORMAT bit  of  the  device  is  set,  then | ||||
| the DWORD  Transfer  Address  points  to  a  one sector buffer | ||||
| which can be used for any purpose.   If  the  NON  IBM  FORMAT | ||||
| bit is  0,  then  this buffer contains the first sector of the | ||||
| FAT; in this case the driver must not alter this buffer  (this | ||||
| mode is  useful  if  all  that  is  desired is to read the FAT | ||||
| ID byte). | ||||
|  | ||||
|     If IBM compatible format  is  used  (NON  IBM  FORMAT  BIT | ||||
| = 0),  then it must be true that the first sector of the first | ||||
| FAT is located at the  same  sector  on  all  possible  media. | ||||
| This is  because  the FAT sector will be read BEFORE the media | ||||
| is actually determined. | ||||
|  | ||||
|     In addition to setting status word, driver  must  set  the | ||||
| Pointer to the BPB on return. | ||||
|  | ||||
|  | ||||
|     In order to allow for many different  OEMs  to  read  each | ||||
| other's disks,  the  following  standard  is  suggested:   The | ||||
| information relating to the BPB  for  a  particular  piece  of | ||||
| media   is  kept  in  the  boot  sector  for  the  media.   In | ||||
| particular, the format of the boot sector is: | ||||
|  | ||||
|             +------------------------------------+ | ||||
|             | 3 BYTE near JUMP to boot code      | | ||||
|             +------------------------------------+ | ||||
|             | 8 BYTES OEM name and version       | | ||||
|          ---+------------------------------------+--- | ||||
|          B  | WORD bytes per sector              | | ||||
|          P  +------------------------------------+ | ||||
|          B  | BYTE sectors per allocation unit   | | ||||
|             +------------------------------------+ | ||||
|          |  | WORD reserved sectors              | | ||||
|          V  +------------------------------------+ | ||||
|             | BYTE number of FATs                | | ||||
|             +------------------------------------+ | ||||
|             | WORD number of root dir entries    | | ||||
|             +------------------------------------+ | ||||
|             | WORD number of sectors in logical  | | ||||
|          ^  | image                              | | ||||
|          |  +------------------------------------+ | ||||
|          B  | BYTE media descriptor              | | ||||
|          P  +------------------------------------+ | ||||
|          B  | WORD number of FAT sectors         | | ||||
|          ---+------------------------------------+--- | ||||
|             | WORD sectors per track             | | ||||
|             +------------------------------------+ | ||||
|             | WORD number of heads               | | ||||
|             +------------------------------------+ | ||||
|             | WORD number of hidden sectors      | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|     The three  words  at the end are optional, the DOS doesn't | ||||
| care about them (since they are not part of  the  BPB).   They | ||||
| are intended  to  help the BIOS understand the media.  Sectors | ||||
| per track may be redundant (could be figured  out  from  total | ||||
| size of  the  disk).  Number of heads is useful for supporting | ||||
| different  multi-head  drives  which  have  the  same  storage | ||||
| capacity, but  a  different  number  of  surfaces.   Number of | ||||
| hidden sectors is useful  for  supporting  drive  partitioning | ||||
| schemes. | ||||
|  | ||||
|  | ||||
|     Currently, the media  descriptor  byte  has  been  defined | ||||
| for a small range of media: | ||||
|  | ||||
|     5 1/4" diskettes: | ||||
|  | ||||
|         Flag bits: | ||||
|             01h - on -> 2 double sided | ||||
|  | ||||
|         All other bits must be on. | ||||
|  | ||||
|     8" disks: | ||||
|         FEh - IBM  3740 format, singled-sided, single-density, | ||||
|             128 bytes per sector,  soft  sectored,  4  sectors | ||||
|             per allocation  unit,  1  reserved sector, 2 FATs, | ||||
|             68 directory entries, 77*26 sectors | ||||
|  | ||||
|         FDh -   8"    IBM    3740    format,    singled-sided, | ||||
|             single-density,   128   bytes   per  sector,  soft | ||||
|             sectored,  4  sectors  per  allocation   unit,   4 | ||||
|             reserved sectors,  2  FATs,  68 directory entries, | ||||
|             77*26 sectors | ||||
|  | ||||
|         FEh - 8"  Double-sided,  double-density,  1024   bytes | ||||
|             per sector, soft sectored, 1 sector per allocation | ||||
|             unit, 1 reserved sector,  2  FATs,  192  directory | ||||
|             entries, 77*8*2 sectors | ||||
|  | ||||
|  | ||||
| STATUS Calls - ES:BX -> | ||||
|             +------------------------------------+ | ||||
|             | 13-BYTE Static Request Header      | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|     All driver must do is  set  status  word  accordingly  and | ||||
| set the busy bit as follows: | ||||
|  | ||||
|     o   For output on  character  devices:   If  it  is  1  on | ||||
|         return, a  write  request  (if  made)  would  wait for | ||||
|         completion of a current request.  If it  is  0,  there | ||||
|         is no  current  request  and a write request (if made) | ||||
|         would start immediately. | ||||
|  | ||||
|     o   For input on character devices with a buffer a  return | ||||
|         of 1  means,  a  read  request  (if  made) would go to | ||||
|         the physical device.  If  it  is  0  on  return,  then | ||||
|         there are  characters  in  the  devices  buffer  and a | ||||
|         read would return  quickly,  it  also  indicates  that | ||||
|         the user  has  typed  something.   The DOS assumes all | ||||
|         character devices have an  input  type  ahead  buffer. | ||||
|         Devices which  don't  have  them  should always return | ||||
|         busy = 0 so  that  the  DOS  won't  hang  waiting  for | ||||
|         something to  get  into  a buffer which doesn't exist. | ||||
|  | ||||
|  | ||||
| FLUSH Calls - ES:BX -> | ||||
|             +------------------------------------+ | ||||
|             | 13-BYTE Static Request Header      | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|     This  call  tells  the  driver  to  flush  (terminate) all | ||||
| pending requests  that  it  has knowledge of.  Its primary use | ||||
| is to flush the input queue on character devices. | ||||
|  | ||||
|  | ||||
| INIT - ES:BX -> | ||||
|             +------------------------------------+ | ||||
|             | 13-BYTE Static Request Header      | | ||||
|             +------------------------------------+ | ||||
|             | BYTE # of units                    | | ||||
|             +------------------------------------+ | ||||
|             | DWORD Break Address                | | ||||
|          ---+------------------------------------+--- | ||||
|             | DWORD Pointer to BPB array         | | ||||
|             | (not set by Character devices)     | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|     The number of units, break address, and  BPB  pointer  are | ||||
| set by the driver. | ||||
|  | ||||
|  | ||||
| FORMAT OF BPB (Bios Parameter Block) - | ||||
|  | ||||
|             +------------------------------------+ | ||||
|             | WORD Sector size in Bytes          | | ||||
|             |    Must be at least 32             | | ||||
|             +------------------------------------+ | ||||
|             | BYTE Sectors/Allocation unit       | | ||||
|             |    Must be a power of 2            | | ||||
|             +------------------------------------+ | ||||
|             | WORD Number of reserved sectors    | | ||||
|             |        May be zero                 | | ||||
|             +------------------------------------+ | ||||
|             | BYTE Number of FATS                | | ||||
|             +------------------------------------+ | ||||
|             | WORD Number of directory entries   | | ||||
|             +------------------------------------+ | ||||
|             | WORD Total number of sectors       | | ||||
|             +------------------------------------+ | ||||
|             | BYTE Media descriptor              | | ||||
|             +------------------------------------+ | ||||
|             | WORD Number of sectors occupied by | | ||||
|             |      FAT                           | | ||||
|             +------------------------------------+ | ||||
|  | ||||
|  | ||||
| THE CLOCK DEVICE | ||||
|  | ||||
|     One of  the  most  popular add on boards seems to be "Real | ||||
| Time CLOCK Boards".  To allow these boards  to  be  integrated | ||||
| into the  system  for TIME and DATE, there is a special device | ||||
| (determined by the attribute word) which is the CLOCK  device. | ||||
| In all  respects  this  device  defines and performs functions | ||||
| like any other character device (most functions will  be  "set | ||||
| done bit,  reset  error  bit,  return).   When a read or write | ||||
| to this device occurs, exactly 6 bytes are transferred.   This | ||||
| I/O can be thought of as transferring 3 words which correspond | ||||
| exactly to the values of AX, CX and  DX  which  were  used  in | ||||
| the old  1.25  DOS  date  and  time  routines.  Thus the first | ||||
| two bytes are a word which is the count of days since  1-1-80. | ||||
| The  third  byte  is  minutes,  the  fourth  hours,  the fifth | ||||
| hundredths of seconds, and the  sixth  seconds.   Reading  the | ||||
| CLOCK device  gets  the  date and time, writing to it sets the | ||||
| date and time. | ||||
|  | ||||