📄 dsk.c
字号:
/****************************************************************/
/* */
/* dsk.c */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#include "dyndata.h"
#ifdef VERSION_STRINGS
static BYTE *dskRcsId =
"$Id: dsk.c,v 1.44 2004/05/29 09:51:47 bartoldeman Exp $";
#endif
#if defined(DEBUG)
#define DebugPrintf(x) printf x
#else
#define DebugPrintf(x)
#endif
/* #define STATIC */
BOOL ASMPASCAL fl_reset(WORD);
COUNT ASMPASCAL fl_diskchanged(WORD);
COUNT ASMPASCAL fl_format(WORD, WORD, WORD, WORD, WORD, UBYTE FAR *);
COUNT ASMPASCAL fl_read(WORD, WORD, WORD, WORD, WORD, UBYTE FAR *);
COUNT ASMPASCAL fl_write(WORD, WORD, WORD, WORD, WORD, UBYTE FAR *);
COUNT ASMPASCAL fl_verify(WORD, WORD, WORD, WORD, WORD, UBYTE FAR *);
COUNT ASMPASCAL fl_setdisktype(WORD, WORD);
COUNT ASMPASCAL fl_setmediatype(WORD, WORD, WORD);
VOID ASMPASCAL fl_readkey(VOID);
extern COUNT ASMPASCAL fl_lba_ReadWrite(BYTE drive, WORD mode,
struct _bios_LBA_address_packet FAR
* dap_p);
#ifdef __WATCOMC__
#pragma aux (pascal) fl_reset modify exact [ax dx]
#pragma aux (pascal) fl_diskchanged modify exact [ax dx]
#pragma aux (pascal) fl_setdisktype modify exact [ax bx dx]
#pragma aux (pascal) fl_readkey modify exact [ax]
#pragma aux (pascal) fl_lba_ReadWrite modify exact [ax dx]
#endif
STATIC int LBA_Transfer(ddt * pddt, UWORD mode, VOID FAR * buffer,
ULONG LBA_address, unsigned total, UWORD * transferred);
#define NENTRY 26 /* total size of dispatch table */
#define LBA_READ 0x4200
#define LBA_WRITE 0x4300
UWORD LBA_WRITE_VERIFY = 0x4302;
#define LBA_VERIFY 0x4400
#define LBA_FORMAT 0xffff /* fake number for FORMAT track
(only for NON-LBA floppies now!) */
/* this buffer must not overlap a 64K boundary
due to DMA transfers
this is certainly true, if located somewhere
at 0xf+1000 and must hold already during BOOT time
*/
UBYTE DiskTransferBuffer[1 * SEC_SIZE];
struct FS_info {
ULONG serialno;
BYTE volume[11];
BYTE fstype[8];
};
extern struct DynS ASM Dyn;
/*TE - array access functions */
ddt *getddt(int dev)
{
return &(((ddt *) Dyn.Buffer)[dev]);
}
STATIC VOID tmark(ddt *pddt)
{
pddt->ddt_fh.ddt_lasttime = ReadPCClock();
}
STATIC BOOL tdelay(ddt *pddt, ULONG ticks)
{
return ReadPCClock() - pddt->ddt_fh.ddt_lasttime >= ticks;
}
#define N_PART 4 /* number of partitions per
table partition */
#define PARTOFF 0x1be
#ifdef PROTO
typedef WORD dsk_proc(rqptr rq, ddt * pddt);
#else
typedef WORD dsk_proc();
#endif
STATIC dsk_proc mediachk, bldbpb, blockio, IoctlQueblk,
Genblkdev, Getlogdev, Setlogdev, blk_Open, blk_Close,
blk_Media, blk_noerr, blk_nondr, blk_error;
STATIC WORD getbpb(ddt * pddt);
#ifdef PROTO
STATIC WORD dskerr(COUNT);
#else
STATIC WORD dskerr();
#endif
/* */
/* the function dispatch table */
/* */
static dsk_proc * const dispatch[NENTRY] =
{
/* disk init is done in diskinit.c, so this should never be called */
blk_error, /* Initialize */
mediachk, /* Media Check */
bldbpb, /* Build BPB */
blk_error, /* Ioctl In */
blockio, /* Input (Read) */
blk_nondr, /* Non-destructive Read */
blk_noerr, /* Input Status */
blk_noerr, /* Input Flush */
blockio, /* Output (Write) */
blockio, /* Output with verify */
blk_noerr, /* Output Status */
blk_noerr, /* Output Flush */
blk_error, /* Ioctl Out */
blk_Open, /* Device Open */
blk_Close, /* Device Close */
blk_Media, /* Removable Media */
blk_noerr, /* Output till busy */
blk_error, /* undefined */
blk_error, /* undefined */
Genblkdev, /* Generic Ioctl Call */
blk_error, /* undefined */
blk_error, /* undefined */
blk_error, /* undefined */
Getlogdev, /* Get Logical Device */
Setlogdev, /* Set Logical Device */
IoctlQueblk /* Ioctl Query */
};
#define hd(x) ((x) & DF_FIXED)
/* ----------------------------------------------------------------------- */
/* F U N C T I O N S --------------------------------------------------- */
/* ----------------------------------------------------------------------- */
COUNT ASMCFUNC FAR blk_driver(rqptr rp)
{
if (rp->r_unit >= blk_dev.dh_name[0] && rp->r_command != C_INIT)
return failure(E_UNIT);
if (rp->r_command > NENTRY)
{
return failure(E_FAILURE); /* general failure */
}
else
return ((*dispatch[rp->r_command]) (rp, getddt(rp->r_unit)));
}
STATIC char template_string[] = "Remove diskette in drive X:\n";
#define DRIVE_POS (sizeof(template_string) - 4)
STATIC WORD play_dj(ddt * pddt)
{
/* play the DJ ... */
if ((pddt->ddt_descflags & (DF_MULTLOG | DF_CURLOG)) == DF_MULTLOG)
{
int i;
ddt *pddt2 = getddt(0);
for (i = 0; i < blk_dev.dh_name[0]; i++, pddt2++)
{
if (pddt->ddt_driveno == pddt2->ddt_driveno &&
(pddt2->ddt_descflags & (DF_MULTLOG | DF_CURLOG)) ==
(DF_MULTLOG | DF_CURLOG))
break;
}
if (i == blk_dev.dh_name[0])
{
put_string("Error in the DJ mechanism!\n"); /* should not happen! */
}
else
{
template_string[DRIVE_POS] = 'A' + pddt2->ddt_logdriveno;
put_string(template_string);
put_string("Insert");
template_string[DRIVE_POS] = 'A' + pddt->ddt_logdriveno;
put_string(template_string + 6);
put_string("Press the any key to continue ... \n");
fl_readkey();
pddt2->ddt_descflags &= ~DF_CURLOG;
pddt->ddt_descflags |= DF_CURLOG;
pokeb(0, 0x504, pddt->ddt_logdriveno);
}
return M_CHANGED;
}
return M_NOT_CHANGED;
}
STATIC WORD diskchange(ddt * pddt)
{
COUNT result;
/* if it's a hard drive, media never changes */
if (hd(pddt->ddt_descflags))
return M_NOT_CHANGED;
if (play_dj(pddt) == M_CHANGED)
return M_CHANGED;
if (pddt->ddt_descflags & DF_CHANGELINE) /* if we can detect a change ... */
{
if ((result = fl_diskchanged(pddt->ddt_driveno)) == 1)
/* check if it has changed... */
return M_CHANGED;
else if (result == 0)
return M_NOT_CHANGED;
}
/* can not detect or error... */
return tdelay(pddt, 37ul) ? M_DONT_KNOW : M_NOT_CHANGED;
}
STATIC WORD mediachk(rqptr rp, ddt * pddt)
{
/* check floppy status */
if (pddt->ddt_descflags & DF_REFORMAT)
{
pddt->ddt_descflags &= ~DF_REFORMAT;
rp->r_mcretcode = M_CHANGED;
}
else if (pddt->ddt_descflags & DF_DISKCHANGE)
{
pddt->ddt_descflags &= ~DF_DISKCHANGE;
rp->r_mcretcode = M_DONT_KNOW;
}
else
{
rp->r_mcretcode = diskchange(pddt);
if (rp->r_mcretcode == M_DONT_KNOW)
{
/* don't know but can check serial number ... */
ULONG serialno = pddt->ddt_serialno;
COUNT result = getbpb(pddt);
if (result != 0)
return (result);
if (serialno != pddt->ddt_serialno)
rp->r_mcretcode = M_CHANGED;
}
}
return S_DONE;
}
/*
* Read Write Sector Zero or Hard Drive Dos Bpb
*/
STATIC WORD RWzero(ddt * pddt, UWORD mode)
{
UWORD done;
return LBA_Transfer(pddt, mode,
(UBYTE FAR *) & DiskTransferBuffer,
pddt->ddt_offset, 1, &done);
}
/*
0 if not set, 1 = a, 2 = b, etc, assume set.
page 424 MS Programmer's Ref.
*/
STATIC WORD Getlogdev(rqptr rp, ddt * pddt)
{
int i;
ddt *pddt2;
if (!(pddt->ddt_descflags & DF_MULTLOG)) {
rp->r_unit = 0;
return S_DONE;
}
pddt2 = getddt(0);
for (i = 0; i < blk_dev.dh_name[0]; i++, pddt2++)
{
if (pddt->ddt_driveno == pddt2->ddt_driveno &&
(pddt2->ddt_descflags & (DF_MULTLOG | DF_CURLOG)) ==
(DF_MULTLOG | DF_CURLOG))
break;
}
rp->r_unit = i+1;
return S_DONE;
}
STATIC WORD Setlogdev(rqptr rp, ddt * pddt)
{
unsigned char unit = rp->r_unit;
Getlogdev(rp, pddt);
if (rp->r_unit == 0)
return S_DONE;
getddt(rp->r_unit - 1)->ddt_descflags &= ~DF_CURLOG;
pddt->ddt_descflags |= DF_CURLOG;
rp->r_unit = unit + 1;
return S_DONE;
}
STATIC WORD blk_Open(rqptr rp, ddt * pddt)
{
UNREFERENCED_PARAMETER(rp);
pddt->ddt_FileOC++;
return S_DONE;
}
STATIC WORD blk_Close(rqptr rp, ddt * pddt)
{
UNREFERENCED_PARAMETER(rp);
pddt->ddt_FileOC--;
return S_DONE;
}
STATIC WORD blk_nondr(rqptr rp, ddt * pddt)
{
UNREFERENCED_PARAMETER(rp);
UNREFERENCED_PARAMETER(pddt);
return S_BUSY | S_DONE;
}
STATIC WORD blk_Media(rqptr rp, ddt * pddt)
{
UNREFERENCED_PARAMETER(rp);
if (hd(pddt->ddt_descflags))
return S_BUSY | S_DONE; /* Hard Drive */
else
return S_DONE; /* Floppy */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -