Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Writing MS-DOS Device Drivers


December 1990/Writing MS-DOS Device Drivers/Listing 1

Listing 1 (block.c) Main Interrupt Routine

#include   <dos.h>
#include   "block.h"

/*
 * normalize()
 *
 * normalize() guarantees that the offset portion of a far
 * pointer is as small as possible. A complete 20-bit address on
 * the processor can be calculated as
 *
 *     (segment * 16) + offset
 *
 * thus, the offset can be kept to a value between 0 and 15. I
 * use the FP_SEG and FP_OFF macro's in Microsoft's dos.h to
 * manipulate the segment and offset of the far pointer. If your
 * compiler doesn't support such a facility, see the  _rawscroll
 * routine in RAW.ASM, where I do it in assembly language.
 *
 * The whole point of this is to allow a lot of pointer
 * incrementing, using just the offset, without worrying about
 * wrapping around.
 */

static void normalize(p)
int far     **p;
   {
   offset       = FP_OFF(*p);
   FP_SEG(*p)   = FP_SEG(*p) + (offset >> 4);
   FP_OFF(*p)   = offset & 017;
   }

/*
 * interrupt()
 *
 * interrupt() takes care of the commands as they come in from
 * the request header. Because of the size of the RAM disk
 * buffer, the driver initialization could not be appended to the
 * back of the driver, and is in-line like everything else.
 */

void    interrupt()
   {
   command      = rh->command;
   start        = rh->b18.io.start;
   count        = rh->b18.io.count;
   transfer     = (int far *) rh->b14.transfer;
   switch (command)
       {
       case    0:       /* driver initialization */
          source            = ram_disk;
          FP_SEG(source)    = FP_SEG(source) + 0x1000;
          normalize(&source);
          rh->b14.transfer  = (char far *) source;
          rh->b18.bpb       = bpb_tab;
          rh->data          = 1;
          rh->status        = DONE;
          break;
       case    1:       /* media check */
          rh->b14.media_change_code   = 1;     /* disk has
                                 * not been changed */
          rh->status      = DONE;
          break;
       case    2:      /* build parameter block */
          rh->b18.bpb = &bpb;
          break;
       case    4:      /*  read */
       case    8:      /*  write */
       case    9:      /*  write with verify */

          If (start > MAX_BLK  <FONT FACE="Symbol" SIZE=2>½<FONT FACE="Symbol" SIZE=2>½ count > MAX_BLK <FONT FACE="Symbol" SIZE=2>½<FONT FACE="Symbol" SIZE=2>½
              start + count > MAX_BLK)
              {
              rh->status = BLK_NOT_FOUND <FONT FACE="Symbol" SIZE=2>½ ERROR;
              break;
              }
          If (command == 4)
              {
              source = ram_disk;
              normalize(&source);
              source += (BLK_SIZE / sizeof(int)) * start;
              dest   = transfer;
              }
          else
              {
              source = transfer;
              dest   = ram_disk;
              normalize(&dest);
              dest   += (BLK_SIZE / sizeof(int)) * start;
              }
          normalize(&dest);
          normalize(&source);
          for (k1 = 0; k1 < count; k1++)
              for (k2 = 0; k2 < BLK_SIZE / sizeof(int); k2++)
                  *dest++ = *source++;
          rh->status = DONE;
          break;
       case    15:    /*  removable media check */
          rh->status = DONE | BUSY;
          break;
       case    5:     /*  non-destructive read */
       case    6:     /*  input status */
       case    7:     /*  flush input buffers */
       case    10:    /*  output status */
       case    11:    /*  flush output buffers */
       case    13:    /*  device open */
       case    14:    /*  device done */
          rh->status = DONE;
          break;
       case    3:     /*  ioctl read */
       case    12:    /*  ioctl write */
       default;
          rh->status = UNKNOWN_COMMAND | ERROR | DONE;
          break;
       }
    }

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.