📄 dsk.c
字号:
STATIC WORD getbpb(ddt * pddt)
{
ULONG count;
bpb *pbpbarray = &pddt->ddt_bpb;
unsigned secs_per_cyl;
WORD ret;
/* pddt->ddt_descflags |= DF_NOACCESS;
* disabled for now - problems with FORMAT ?? */
/* set drive to not accessible and changed */
if (diskchange(pddt) != M_NOT_CHANGED)
pddt->ddt_descflags |= DF_DISKCHANGE;
ret = RWzero(pddt, LBA_READ);
if (ret != 0)
return (dskerr(ret));
pbpbarray->bpb_nbyte = getword(&DiskTransferBuffer[BT_BPB]);
if (DiskTransferBuffer[0x1fe] != 0x55
|| DiskTransferBuffer[0x1ff] != 0xaa || pbpbarray->bpb_nbyte != 512)
{
/* copy default bpb to be sure that there is no bogus data */
memcpy(pbpbarray, &pddt->ddt_defbpb, sizeof(bpb));
return S_DONE;
}
pddt->ddt_descflags &= ~DF_NOACCESS; /* set drive to accessible */
/*TE ~ 200 bytes*/
memcpy(pbpbarray, &DiskTransferBuffer[BT_BPB], sizeof(bpb));
/*?? */
/* 2b is fat16 volume label. if memcmp, then offset 0x36.
if (fstrncmp((BYTE *) & DiskTransferBuffer[0x36], "FAT16",5) == 0 ||
fstrncmp((BYTE *) & DiskTransferBuffer[0x36], "FAT12",5) == 0) {
TE: I'm not sure, what the _real_ decision point is, however MSDN
'A_BF_BPB_SectorsPerFAT
The number of sectors per FAT.
Note: This member will always be zero in a FAT32 BPB.
Use the values from A_BF_BPB_BigSectorsPerFat...
*/
{
struct FS_info *fs = (struct FS_info *)&DiskTransferBuffer[0x27];
#ifdef WITHFAT32
if (pbpbarray->bpb_nfsect == 0)
{
/* FAT32 boot sector */
fs = (struct FS_info *)&DiskTransferBuffer[0x43];
}
#endif
pddt->ddt_serialno = getlong(&fs->serialno);
memcpy(pddt->ddt_volume, fs->volume, sizeof fs->volume);
memcpy(pddt->ddt_fstype, fs->fstype, sizeof fs->fstype);
}
#ifdef DSK_DEBUG
printf("BPB_NBYTE = %04x\n", pbpbarray->bpb_nbyte);
printf("BPB_NSECTOR = %02x\n", pbpbarray->bpb_nsector);
printf("BPB_NRESERVED = %04x\n", pbpbarray->bpb_nreserved);
printf("BPB_NFAT = %02x\n", pbpbarray->bpb_nfat);
printf("BPB_NDIRENT = %04x\n", pbpbarray->bpb_ndirent);
printf("BPB_NSIZE = %04x\n", pbpbarray->bpb_nsize);
printf("BPB_MDESC = %02x\n", pbpbarray->bpb_mdesc);
printf("BPB_NFSECT = %04x\n", pbpbarray->bpb_nfsect);
#endif
count =
pbpbarray->bpb_nsize == 0 ?
pbpbarray->bpb_huge : pbpbarray->bpb_nsize;
secs_per_cyl = pbpbarray->bpb_nheads * pbpbarray->bpb_nsecs;
if (secs_per_cyl == 0)
{
tmark(pddt);
return failure(E_FAILURE);
}
/* this field is problematic for partitions > 65535 cylinders,
in general > 512 GiB. However: we are not using it ourselves. */
pddt->ddt_ncyl = (UWORD)((count + (secs_per_cyl - 1)) / secs_per_cyl);
tmark(pddt);
#ifdef DSK_DEBUG
printf("BPB_NSECS = %04x\n", pbpbarray->bpb_nsecs);
printf("BPB_NHEADS = %04x\n", pbpbarray->bpb_nheads);
printf("BPB_HIDDEN = %08lx\n", pbpbarray->bpb_hidden);
printf("BPB_HUGE = %08lx\n", pbpbarray->bpb_huge);
#endif
return 0;
}
STATIC WORD bldbpb(rqptr rp, ddt * pddt)
{
WORD result;
if ((result = getbpb(pddt)) != 0)
return result;
rp->r_bpptr = &pddt->ddt_bpb;
return S_DONE;
}
STATIC WORD IoctlQueblk(rqptr rp, ddt * pddt)
{
UNREFERENCED_PARAMETER(pddt);
#ifdef WITHFAT32
if (rp->r_cat == 8 || rp->r_cat == 0x48)
#else
if (rp->r_cat == 8)
#endif
{
switch (rp->r_fun)
{
case 0x46:
case 0x47:
case 0x60:
case 0x66:
case 0x67:
return S_DONE;
}
}
return failure(E_CMD);
}
STATIC COUNT Genblockio(ddt * pddt, UWORD mode, WORD head, WORD track,
WORD sector, WORD count, VOID FAR * buffer)
{
UWORD transferred;
/* apparently sector is ZERO, not ONE based !!! */
return LBA_Transfer(pddt, mode, buffer,
((ULONG) track * pddt->ddt_bpb.bpb_nheads + head) *
(ULONG) pddt->ddt_bpb.bpb_nsecs +
pddt->ddt_offset + sector, count, &transferred);
}
STATIC WORD Genblkdev(rqptr rp, ddt * pddt)
{
int ret;
unsigned descflags = pddt->ddt_descflags;
#ifdef WITHFAT32
int extended = 0;
if (rp->r_cat == 0x48)
extended = 1;
else
#endif
if (rp->r_cat != 8)
return failure(E_CMD);
switch (rp->r_fun)
{
case 0x40: /* set device parameters */
{
struct gblkio FAR *gblp = rp->r_io;
bpb *pbpb;
pddt->ddt_type = gblp->gbio_devtype;
pddt->ddt_descflags = (descflags & ~3) | (gblp->gbio_devattrib & 3)
| (DF_DPCHANGED | DF_REFORMAT);
pddt->ddt_ncyl = gblp->gbio_ncyl;
/* use default dpb or current bpb? */
pbpb =
(gblp->gbio_spcfunbit & 0x01) ==
0 ? &pddt->ddt_defbpb : &pddt->ddt_bpb;
#ifdef WITHFAT32
fmemcpy(pbpb, &gblp->gbio_bpb,
extended ? sizeof(gblp->gbio_bpb) : BPB_SIZEOF);
#else
fmemcpy(pbpb, &gblp->gbio_bpb, sizeof(gblp->gbio_bpb));
#endif
/*pbpb->bpb_nsector = gblp->gbio_nsecs; */
break;
}
case 0x41: /* write track */
{
struct gblkrw FAR *rw = rp->r_rw;
ret = Genblockio(pddt, LBA_WRITE, rw->gbrw_head, rw->gbrw_cyl,
rw->gbrw_sector, rw->gbrw_nsecs, rw->gbrw_buffer);
if (ret != 0)
return dskerr(ret);
}
break;
case 0x42: /* format/verify track */
{
struct gblkfv FAR *fv = rp->r_fv;
COUNT tracks;
struct thst {
UBYTE track, head, sector, type;
} *addrfield, afentry;
pddt->ddt_descflags &= ~DF_DPCHANGED;
if (hd(descflags))
{
/* XXX no low-level formatting for hard disks implemented */
fv->gbfv_spcfunbit = 1; /* "not supported by bios" */
return S_DONE;
}
if (descflags & DF_DPCHANGED)
{
/* first try newer setmediatype function */
ret = fl_setmediatype(pddt->ddt_driveno, pddt->ddt_ncyl,
pddt->ddt_bpb.bpb_nsecs);
if (ret == 0xc)
{
/* specified tracks, sectors/track not allowed for drive */
fv->gbfv_spcfunbit = 2;
return dskerr(ret);
}
else if (ret == 0x80)
{
fv->gbfv_spcfunbit = 3; /* no disk in drive */
return dskerr(ret);
}
else if (ret != 0)
/* otherwise, setdisktype */
{
unsigned char type;
unsigned tracks, secs;
if ((fv->gbfv_spcfunbit & 1) &&
(ret =
fl_read(pddt->ddt_driveno, 0, 0, 1, 1,
DiskTransferBuffer)) != 0)
{
fv->gbfv_spcfunbit = 3; /* no disk in drive */
return dskerr(ret);
}
/* type 1: 320/360K disk in 360K drive */
/* type 2: 320/360K disk in 1.2M drive */
tracks = pddt->ddt_ncyl;
secs = pddt->ddt_bpb.bpb_nsecs;
type = pddt->ddt_type + 1;
if (!(tracks == 40 && (secs == 9 || secs == 8) && type < 3))
{
/* type 3: 1.2M disk in 1.2M drive */
/* type 4: 720kb disk in 1.44M or 720kb drive */
type++;
if (type == 9) /* 1.44M drive */
type = 4;
if (!(tracks == 80 && ((secs == 15 && type == 3) ||
(secs == 9 && type == 4))))
{
/* specified tracks, sectors/track not allowed for drive */
fv->gbfv_spcfunbit = 2;
return dskerr(0xc);
}
}
fl_setdisktype(pddt->ddt_driveno, type);
}
}
if (fv->gbfv_spcfunbit & 1)
return S_DONE;
afentry.type = 2; /* 512 byte sectors */
afentry.track = fv->gbfv_cyl;
afentry.head = fv->gbfv_head;
for (tracks = fv->gbfv_spcfunbit & 2 ? fv->gbfv_ntracks : 1;
tracks > 0; tracks--)
{
addrfield = (struct thst *)DiskTransferBuffer;
if (afentry.track > pddt->ddt_ncyl)
return failure(E_FAILURE);
for (afentry.sector = 1;
afentry.sector <= pddt->ddt_bpb.bpb_nsecs; afentry.sector++)
memcpy(addrfield++, &afentry, sizeof(afentry));
ret =
Genblockio(pddt, LBA_FORMAT, afentry.head, afentry.track, 0,
pddt->ddt_bpb.bpb_nsecs, DiskTransferBuffer);
if (ret != 0)
return dskerr(ret);
}
afentry.head++;
if (afentry.head >= pddt->ddt_bpb.bpb_nheads)
{
afentry.head = 0;
afentry.track++;
}
}
/* fall through to verify */
case 0x62: /* verify track */
{
struct gblkfv FAR *fv = rp->r_fv;
ret = Genblockio(pddt, LBA_VERIFY, fv->gbfv_head, fv->gbfv_cyl, 0,
(fv->gbfv_spcfunbit ?
fv->gbfv_ntracks * pddt->ddt_defbpb.bpb_nsecs :
pddt->ddt_defbpb.bpb_nsecs), DiskTransferBuffer);
if (ret != 0)
return dskerr(ret);
fv->gbfv_spcfunbit = 0; /* success */
}
break;
case 0x46: /* set volume serial number */
{
struct Gioc_media FAR *gioc = rp->r_gioc;
struct FS_info *fs;
ret = getbpb(pddt);
if (ret != 0)
return (ret);
fs = (struct FS_info *)&DiskTransferBuffer
[(pddt->ddt_bpb.bpb_nfsect != 0 ? 0x27 : 0x43)];
fs->serialno = gioc->ioc_serialno;
pddt->ddt_serialno = fs->serialno;
ret = RWzero(pddt, LBA_WRITE);
if (ret != 0)
return (dskerr(ret));
}
break;
case 0x47: /* set access flag */
{
struct Access_info FAR *ai = rp->r_ai;
pddt->ddt_descflags = (descflags & ~DF_NOACCESS) |
(ai->AI_Flag ? 0 : DF_NOACCESS);
}
break;
case 0x60: /* get device parameters */
{
struct gblkio FAR *gblp = rp->r_io;
bpb *pbpb;
gblp->gbio_devtype = pddt->ddt_type;
gblp->gbio_devattrib = descflags & 3;
/* 360 kb disk in 1.2 MB drive */
gblp->gbio_media = (pddt->ddt_type == 1) && (pddt->ddt_ncyl == 40);
gblp->gbio_ncyl = pddt->ddt_ncyl;
/* use default dpb or current bpb? */
pbpb =
(gblp->gbio_spcfunbit & 0x01) ==
0 ? &pddt->ddt_defbpb : &pddt->ddt_bpb;
#ifdef WITHFAT32
fmemcpy(&gblp->gbio_bpb, pbpb,
extended ? sizeof(gblp->gbio_bpb) : BPB_SIZEOF);
#else
fmemcpy(&gblp->gbio_bpb, pbpb, sizeof(gblp->gbio_bpb));
#endif
/*gblp->gbio_nsecs = pbpb->bpb_nsector; */
break;
}
case 0x61: /* read track */
{
struct gblkrw FAR *rw = rp->r_rw;
ret = Genblockio(pddt, LBA_READ, rw->gbrw_head, rw->gbrw_cyl,
rw->gbrw_sector, rw->gbrw_nsecs, rw->gbrw_buffer);
if (ret != 0)
return dskerr(ret);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -