home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_08_12
/
8n12042a
< prev
next >
Wrap
Text File
|
1990-10-15
|
4KB
|
123 lines
/*
* 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 || count > MAX_BLK ||
start + count > MAX_BLK)
{
rh->status = BLK_NOT_FOUND | 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;
}
}