DSK.C
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:19k
- /****************************************************************/
- /* */
- /* 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 "../../hdr/portab.h"
- #include "globals.h"
- /* $Logfile: C:/dos-c/src/kernel/dsk.c_v $ */
- #ifdef VERSION_STRINGS
- static BYTE *dskRcsId = "$Header: C:/dos-c/src/kernel/dsk.c_v 1.6 04 Jan 1998 23:15:16 patv $";
- #endif
- /* $Log: C:/dos-c/src/kernel/dsk.c_v $
- *
- * Rev 1.6 04 Jan 1998 23:15:16 patv
- * Changed Log for strip utility
- *
- * Rev 1.5 10 Jan 1997 5:41:48 patv
- * Modified for extended partition support
- *
- * Rev 1.4 29 May 1996 21:03:32 patv
- * bug fixes for v0.91a
- *
- * Rev 1.3 19 Feb 1996 3:21:36 patv
- * Added NLS, int2f and config.sys processing
- *
- * Rev 1.2 01 Sep 1995 17:54:18 patv
- * First GPL release.
- *
- * Rev 1.1 30 Jul 1995 20:52:00 patv
- * Eliminated version strings in ipl
- *
- * Rev 1.0 02 Jul 1995 8:32:42 patv
- * Initial revision.
- */
- /* $EndLog$ */
- #ifdef PROTO
- BOOL fl_reset(VOID);
- COUNT fl_rd_status(WORD);
- COUNT fl_read(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
- COUNT fl_write(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
- BOOL fl_verify(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
- BOOL fl_format(WORD, BYTE FAR *);
- #else
- BOOL fl_reset();
- COUNT fl_rd_status();
- COUNT fl_read();
- COUNT fl_write();
- BOOL fl_verify();
- BOOL fl_format();
- #endif
- #define NDEV 8 /* only one for demo */
- #define SEC_SIZE 512 /* size of sector in bytes */
- #define N_RETRY 5 /* number of retries permitted */
- #define NENTRY 25 /* total size of dispatch table */
- union
- {
- BYTE bytes[2 * SEC_SIZE];
- boot boot_sector;
- } buffer;
- static struct media_info
- {
- ULONG mi_size; /* physical sector count */
- UWORD mi_heads; /* number of heads (sides) */
- UWORD mi_cyls; /* number of cyl/drive */
- UWORD mi_sectors; /* number of sectors/cyl */
- ULONG mi_offset; /* relative partition offset */
- BYTE mi_drive; /* BIOS drive number */
- COUNT mi_partidx; /* Index to partition array */
- };
- static struct media_info miarray[NDEV]; /* Internal media info structs */
- static bpb bpbarray[NDEV]; /* BIOS parameter blocks */
- static bpb *bpbptrs[NDEV]; /* pointers to bpbs */
- #define N_PART 4 /* number of partitions per
- table partition */
- static WORD head, track, sector, ret; /* globals for blockio */
- static WORD count;
- static COUNT nUnits; /* number of returned units */
- static COUNT nPartitions; /* number of DOS partitions */
- #define PARTOFF 0x1be
- static struct
- {
- BYTE peDrive; /* BIOS drive number */
- BYTE peBootable;
- BYTE peBeginHead;
- BYTE peBeginSector;
- UWORD peBeginCylinder;
- BYTE peFileSystem;
- BYTE peEndHead;
- BYTE peEndSector;
- UWORD peEndCylinder;
- LONG peStartSector;
- LONG peSectors;
- LONG peAbsStart; /* Absolute sector start */
- } dos_partition[NDEV - 2];
- #ifdef PROTO
- WORD init(rqptr), mediachk(rqptr), bldbpb(rqptr), blockio(rqptr), blk_error(rqptr);
- COUNT ltop(WORD *, WORD *, WORD *, COUNT, COUNT, LONG, byteptr);
- WORD dskerr(COUNT);
- COUNT processtable(COUNT ptDrive, BYTE ptHead, UWORD ptCylinder, BYTE ptSector, LONG ptAccuOff);
- #else
- WORD init(), mediachk(), bldbpb(), blockio(), blk_error();
- WORD dskerr();
- COUNT processtable();
- #endif
- /* */
- /* the function dispatch table */
- /* */
- #ifdef PROTO
- static WORD (*dispatch[NENTRY]) (rqptr) =
- #else
- static WORD (*dispatch[NENTRY]) () =
- #endif
- {
- init, /* Initialize */
- mediachk, /* Media Check */
- bldbpb, /* Build BPB */
- blk_error, /* Ioctl In */
- blockio, /* Input (Read) */
- blk_error, /* Non-destructive Read */
- blk_error, /* Input Status */
- blk_error, /* Input Flush */
- blockio, /* Output (Write) */
- blockio, /* Output with verify */
- blk_error, /* Output Status */
- blk_error, /* Output Flush */
- blk_error, /* Ioctl Out */
- blk_error, /* Device Open */
- blk_error, /* Device Close */
- blk_error, /* Removable Media */
- blk_error, /* Output till busy */
- blk_error, /* undefined */
- blk_error, /* undefined */
- blk_error, /* Generic Ioctl */
- blk_error, /* undefined */
- blk_error, /* undefined */
- blk_error, /* undefined */
- blk_error, /* Get Logical Device */
- blk_error /* Set Logical Device */
- };
- #define SIZEOF_PARTENT 16
- #define FAT12 0x01
- #define FAT16SMALL 0x04
- #define EXTENDED 0x05
- #define FAT16LARGE 0x06
- #define hd(x) ((x) & 0x80)
- COUNT
- processtable (COUNT ptDrive, BYTE ptHead, UWORD ptCylinder,
- BYTE ptSector, LONG ptAccuOff)
- {
- struct /* Temporary partition table */
- {
- BYTE peBootable;
- BYTE peBeginHead;
- BYTE peBeginSector;
- UWORD peBeginCylinder;
- BYTE peFileSystem;
- BYTE peEndHead;
- BYTE peEndSector;
- UWORD peEndCylinder;
- LONG peStartSector;
- LONG peSectors;
- } temp_part[N_PART];
- REG retry = N_RETRY;
- UBYTE packed_byte, pb1;
- COUNT Part;
- /* Read partition table */
- do
- {
- ret = fl_read ((WORD)ptDrive, (WORD)ptHead, (WORD)ptCylinder,
- (WORD)ptSector, (WORD)1, (byteptr)&buffer);
- } while (ret != 0 && --retry > 0);
- if(ret != 0)
- return FALSE;
- /* Read each partition into temporary array */
- for (Part = 0; Part < N_PART; Part++)
- {
- REG BYTE *p =
- (BYTE *)&buffer.bytes[PARTOFF + (Part * SIZEOF_PARTENT)];
- getbyte((VOID *)p, &temp_part[Part].peBootable);
- ++p;
- getbyte((VOID *)p, &temp_part[Part].peBeginHead);
- ++p;
- getbyte((VOID *)p, &packed_byte);
- temp_part[Part].peBeginSector = packed_byte & 0x3f;
- ++p;
- getbyte((VOID *)p, &pb1);
- ++p;
- temp_part[Part].peBeginCylinder = pb1 + ((UWORD)(0xc0 & packed_byte) << 2);
- getbyte((VOID *)p, &temp_part[Part].peFileSystem);
- ++p;
- getbyte((VOID *)p, &temp_part[Part].peEndHead);
- ++p;
- getbyte((VOID *)p, &packed_byte);
- temp_part[Part].peEndSector = packed_byte & 0x3f;
- ++p;
- getbyte((VOID *)p, &pb1);
- ++p;
- temp_part[Part].peEndCylinder = pb1 + ((UWORD)(0xc0 & packed_byte) << 2);
- getlong((VOID *)p, &temp_part[Part].peStartSector);
- p += sizeof(LONG);
- getlong((VOID *)p, &temp_part[Part].peSectors);
- };
- /* Walk through the table, add DOS partitions to global
- array and process extended partitions */
- for (Part = 0; Part < N_PART && nUnits < NDEV; Part++)
- {
- if (temp_part[Part].peFileSystem == FAT12 ||
- temp_part[Part].peFileSystem == FAT16SMALL ||
- temp_part[Part].peFileSystem == FAT16LARGE)
- {
- miarray[nUnits].mi_offset =
- temp_part[Part].peStartSector + ptAccuOff;
- miarray[nUnits].mi_drive = ptDrive;
- miarray[nUnits].mi_partidx = nPartitions;
- nUnits++;
- dos_partition[nPartitions].peDrive = ptDrive;
- dos_partition[nPartitions].peBootable =
- temp_part[Part].peBootable;
- dos_partition[nPartitions].peBeginHead =
- temp_part[Part].peBeginHead;
- dos_partition[nPartitions].peBeginSector =
- temp_part[Part].peBeginSector;
- dos_partition[nPartitions].peBeginCylinder =
- temp_part[Part].peBeginCylinder;
- dos_partition[nPartitions].peFileSystem =
- temp_part[Part].peFileSystem;
- dos_partition[nPartitions].peEndHead =
- temp_part[Part].peEndHead;
- dos_partition[nPartitions].peEndSector =
- temp_part[Part].peEndSector;
- dos_partition[nPartitions].peEndCylinder =
- temp_part[Part].peEndCylinder;
- dos_partition[nPartitions].peStartSector =
- temp_part[Part].peStartSector;
- dos_partition[nPartitions].peSectors =
- temp_part[Part].peSectors;
- dos_partition[nPartitions].peAbsStart =
- temp_part[Part].peStartSector + ptAccuOff;
- nPartitions++;
- }
- else if (temp_part[Part].peFileSystem == EXTENDED)
- {
- /* call again to process extended part table */
- processtable (ptDrive,
- temp_part[Part].peBeginHead,
- temp_part[Part].peBeginCylinder,
- temp_part[Part].peBeginSector,
- temp_part[Part].peStartSector + ptAccuOff);
- };
- };
- return TRUE;
- }
- COUNT
- blk_driver (rqptr rp)
- {
- if(rp -> r_unit >= nUnits && 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));
- }
- static WORD
- init (rqptr rp)
- {
- COUNT HardDrive, Unit;
- /* Reset the drives */
- fl_reset();
- /* Initial number of disk units */
- nUnits = 2;
- /* Initial number of DOS partitions */
- nPartitions = 0;
- /* Setup media info and BPBs arrays */
- for (Unit = 0; Unit < NDEV; Unit++)
- {
- miarray[Unit].mi_size = 720l;
- miarray[Unit].mi_heads = 2;
- miarray[Unit].mi_cyls = 40;
- miarray[Unit].mi_sectors = 9;
- miarray[Unit].mi_offset = 0l;
- miarray[Unit].mi_drive = Unit;
- bpbarray[Unit].bpb_nbyte = SEC_SIZE;
- bpbarray[Unit].bpb_nsector = 2;
- bpbarray[Unit].bpb_nreserved = 1;
- bpbarray[Unit].bpb_nfat = 2;
- bpbarray[Unit].bpb_ndirent = 112;
- bpbarray[Unit].bpb_nsize = 720l;
- bpbarray[Unit].bpb_mdesc = 0xfd;
- bpbarray[Unit].bpb_nfsect = 2;
- bpbptrs[Unit] = &bpbarray[Unit];
- };
- for(HardDrive = 0; HardDrive <= 0; HardDrive++) /* only one hard drive for now */
- {
- /* Process primary partition table */
- if (!processtable ((HardDrive | 0x80), 0, 0l, 1, 0l))
- /* Exit if no hard drive */
- break;
- };
- rp -> r_nunits = nUnits;
- rp -> r_bpbptr = bpbptrs;
- rp -> r_endaddr = device_end();
- return S_DONE;
- }
- static WORD
- mediachk (rqptr rp)
- {
- if(hd(miarray[rp -> r_unit].mi_drive))
- rp -> r_mcretcode = M_NOT_CHANGED;
- else
- rp -> r_mcretcode = tdelay((LONG)37) ? M_DONT_KNOW : M_NOT_CHANGED;
- return S_DONE;
- }
- static WORD
- bldbpb (rqptr rp)
- {
- REG retry = N_RETRY;
- ULONG count;
- byteptr trans;
- WORD local_word;
- if(hd(miarray[rp -> r_unit].mi_drive))
- {
- COUNT partidx = miarray[rp -> r_unit].mi_partidx;
- head = dos_partition[partidx].peBeginHead;
- sector = dos_partition[partidx].peBeginSector;
- track = dos_partition[partidx].peBeginCylinder;
- }
- else
- {
- head = 0;
- sector = 1;
- track = 0;
- }
- do
- {
- ret = fl_read((WORD)miarray[rp -> r_unit].mi_drive,
- (WORD)head, (WORD)track, (WORD)sector, (WORD)1, (byteptr)&buffer);
- } while (ret != 0 && --retry > 0);
- if(ret != 0)
- return(dskerr(ret));
- getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NBYTE]), &bpbarray[rp -> r_unit].bpb_nbyte);
- getbyte(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NSECTOR]), &bpbarray[rp -> r_unit].bpb_nsector);
- getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NRESERVED]), &bpbarray[rp -> r_unit].bpb_nreserved);
- getbyte(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NFAT]), &bpbarray[rp -> r_unit].bpb_nfat);
- getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NDIRENT]), &bpbarray[rp -> r_unit].bpb_ndirent);
- getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NSIZE]), &bpbarray[rp -> r_unit].bpb_nsize);
- getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NSIZE]), &bpbarray[rp -> r_unit].bpb_nsize);
- getbyte(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_MDESC]), &bpbarray[rp -> r_unit].bpb_mdesc);
- getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NFSECT]), &bpbarray[rp -> r_unit].bpb_nfsect);
- getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NSECS]), &bpbarray[rp -> r_unit].bpb_nsecs);
- getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NHEADS]), &bpbarray[rp -> r_unit].bpb_nheads);
- getlong(&((((BYTE *)&buffer.bytes[BT_BPB])[BPB_HIDDEN])), &bpbarray[rp -> r_unit].bpb_hidden);
- getlong(&((((BYTE *)&buffer.bytes[BT_BPB])[BPB_HUGE])), &bpbarray[rp -> r_unit].bpb_huge);
- #ifdef DSK_DEBUG
- printf("BPB_NBYTE = %04xn", bpbarray[rp -> r_unit].bpb_nbyte);
- printf("BPB_NSECTOR = %02xn", bpbarray[rp -> r_unit].bpb_nsector);
- printf("BPB_NRESERVED = %04xn", bpbarray[rp -> r_unit].bpb_nreserved);
- printf("BPB_NFAT = %02xn", bpbarray[rp -> r_unit].bpb_nfat);
- printf("BPB_NDIRENT = %04xn", bpbarray[rp -> r_unit].bpb_ndirent);
- printf("BPB_NSIZE = %04xn", bpbarray[rp -> r_unit].bpb_nsize);
- printf("BPB_MDESC = %02xn", bpbarray[rp -> r_unit].bpb_mdesc);
- printf("BPB_NFSECT = %04xn", bpbarray[rp -> r_unit].bpb_nfsect);
- #endif
- rp -> r_bpptr = &bpbarray[rp -> r_unit];
- count = miarray[rp -> r_unit].mi_size =
- bpbarray[rp -> r_unit].bpb_nsize == 0 ?
- bpbarray[rp -> r_unit].bpb_huge :
- bpbarray[rp -> r_unit].bpb_nsize;
- getword((&(((BYTE *)&buffer.bytes[BT_BPB])[BPB_NHEADS])), &miarray[rp -> r_unit].mi_heads);
- head = miarray[rp -> r_unit].mi_heads;
- getword((&(((BYTE *)&buffer.bytes[BT_BPB])[BPB_NSECS])), &miarray[rp -> r_unit].mi_sectors);
- if(miarray[rp -> r_unit].mi_size == 0)
- getlong(&((((BYTE *)&buffer.bytes[BT_BPB])[BPB_HUGE])), &miarray[rp -> r_unit].mi_size);
- sector = miarray[rp -> r_unit].mi_sectors;
- if(head == 0 || sector == 0)
- {
- tmark();
- return failure(E_FAILURE);
- }
- miarray[rp -> r_unit].mi_cyls = count / (head * sector);
- tmark();
- #ifdef DSK_DEBUG
- printf("BPB_NSECS = %04xn", sector);
- printf("BPB_NHEADS = %04xn", head);
- printf("BPB_HIDDEN = %08lxn", bpbarray[rp -> r_unit].bpb_hidden);
- printf("BPB_HUGE = %08lxn", bpbarray[rp -> r_unit].bpb_huge);
- #endif
- return S_DONE;
- }
- static WORD
- blockio (rqptr rp)
- {
- REG retry = N_RETRY, remaining;
- UWORD cmd, total;
- ULONG start;
- byteptr trans;
- cmd = rp -> r_command;
- total = 0;
- trans = rp -> r_trans;
- tmark();
- for
- (
- remaining = rp -> r_count,
- start = (rp -> r_start != HUGECOUNT ? rp -> r_start : rp -> r_huge)
- + miarray[rp -> r_unit].mi_offset;
- remaining > 0;
- remaining -= count, trans += count * SEC_SIZE, start += count
- )
- {
- if(ltop(&track, §or, &head, rp -> r_unit, 1, start, trans) != 1)
- {
- /* printf("split sector at 0x%lx", trans);*/
- }
- count = ltop(&track, §or, &head, rp -> r_unit, remaining, start, trans);
- total += count;
- do
- {
- switch(cmd)
- {
- case C_INPUT:
- ret = fl_read((WORD)miarray[rp -> r_unit].mi_drive, (WORD)head, (WORD)track, (WORD)sector, (WORD)count, trans);
- break;
- case C_OUTPUT:
- case C_OUTVFY:
- ret = fl_write((WORD)miarray[rp -> r_unit].mi_drive, (WORD)head, (WORD)track, (WORD)sector, (WORD)count, trans);
- break;
- default:
- return failure(E_FAILURE);
- }
- } while (ret != 0 && --retry > 0);
- if(ret != 0)
- {
- rp -> r_count = 0;
- return dskerr(ret);
- }
- if(cmd == C_OUTVFY)
- {
- ret = fl_verify((WORD)miarray[rp -> r_unit].mi_drive, (WORD)head, (WORD)track, (WORD)sector, (WORD)count, rp -> r_trans);
- if(ret != 0)
- {
- rp -> r_count = 0;
- return dskerr(ret);
- }
- }
- }
- rp -> r_count = total;
- return S_DONE;
- }
- static WORD
- blk_error (rqptr rp)
- {
- rp -> r_count = 0;
- return failure(E_FAILURE); /* general failure */
- }
- static WORD
- dskerr (COUNT code)
- {
- /* printf("diskette error:nhead = %dntrack = %dnsector = %dncount = %dn",
- head, track, sector, count);*/
- switch(code & 0x03)
- {
- case 1: /* invalid command - general failure */
- if(code & 0x08)
- return(E_FAILURE);
- else
- return failure(E_CMD);
- case 2: /* address mark not found - general failure */
- return failure(E_FAILURE);
- case 3: /* write protect */
- return failure(E_WRPRT);
- default:
- if(code & 0x80) /* time-out */
- return failure(E_NOTRDY);
- else if(code & 0x40) /* seek error */
- return failure(E_SEEK);
- else if(code & 0x10) /* CRC error */
- return failure(E_CRC);
- else if(code & 0x04)
- return failure(E_NOTFND);
- else
- return failure(E_FAILURE);
- }
- }
- /* */
- /* Do logical block number to physical head/track/sector mapping */
- /* */
- static COUNT
- ltop (WORD *trackp, WORD *sectorp, WORD *headp, REG COUNT unit, COUNT count, LONG strt_sect, byteptr strt_addr)
- {
- #ifdef I86
- ULONG ltemp;
- #endif
- REG ls, ps;
- #ifdef I86
- /* Adjust for segmented architecture */
- ltemp = (((ULONG)mk_segment(strt_addr) << 4) + mk_offset(strt_addr)) & 0xffff;
- /* Test for 64K boundary crossing and return count large */
- /* enough not to exceed the threshold. */
- count = (((ltemp + SEC_SIZE * count) & 0xffff0000l) != 0l)
- ? (0xffffl - ltemp) / SEC_SIZE
- : count;
- #endif
- *trackp = strt_sect / (miarray[unit].mi_heads * miarray[unit].mi_sectors);
- *sectorp = strt_sect % miarray[unit].mi_sectors + 1;
- *headp = (strt_sect % (miarray[unit].mi_sectors * miarray[unit].mi_heads))
- / miarray[unit].mi_sectors;
- if(((ls = *headp * miarray[unit].mi_sectors + *sectorp - 1) + count) >
- (ps = miarray[unit].mi_heads * miarray[unit].mi_sectors))
- count = ps - ls;
- return count;
- }