home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2000 May
/
Chip_2000-05_cd2.bin
/
dosutils
/
partprog
/
pdisk.arc
/
RDPART.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-12
|
7KB
|
268 lines
#include "part.h"
#include <bios.h>
#include <dos.h>
#include <malloc.h>
#include <errno.h>
BOOT *master_boot_rec, /* master boot record of currently selected disk */
*part_boot_rec[4]; /* boot record of each (active) logical partition */
static word start_mode, start_page;
byte changed_parms; /* if this byte is set, save_tbl (below) has
* a ptr to the original (BIOS or whatever)
* disk table, and must be reset.
*/
DISK_TABLE far *fd_tbl,
far *save_tbl;
byte num_disks,
fixed_disk,
_numsecs;
word _shprod;
extern word sector_size;
PARTDATA part_data[4];
extern int dotrans(dword relsect,word startsec,void *buf,word numsec,word op);
void
init() /* initialize tables from a given physical disk */
{
static byte _init = 0;
static word old_sector_size = 0;
struct diskinfo_t diskinfo;
int i;
/* if first time through, fill num_disks */
if(! _init) {
_init = 1;
diskinfo.drive = fixed_disk;
_bios_disk(8,&diskinfo);
if((num_disks = diskinfo.drive) == 0) {
fprintf(stderr,"No fixed disks attached.\n");
exit(1);
/* NOTREACHED */
}
if(num_disks==1 && fixed_disk==DISK1) {
fprintf(stderr,"Only one disk attached.\n");
exit(2);
/* NOTREACHED */
}
start_page = scr_gapage();
scr_sapage(0);
start_mode = scr_gmode();
switch(start_mode) {
case 0:
case 5:
case 6:
scr_smode(2);
break;
case 1:
case 4:
scr_smode(3);
break;
}
master_boot_rec = (BOOT *)malloc(sector_size);
for(i=0;i<4;i++)
part_boot_rec[i] = (BOOT *)malloc(sector_size);
}
else {
if(old_sector_size != sector_size) {
master_boot_rec = (BOOT *)realloc(master_boot_rec,sector_size);
for(i=0; i<4; i++)
part_boot_rec[i] = (BOOT *)realloc(part_boot_rec[i],sector_size);
}
if(changed_parms) {
/* we cast the table vector as a pointer to a far interrupt handler
* function returning void, since that is what _dos_setvect expects.
*/
_dos_setvect(changed_parms==DISK1 ? 0x46 : 0x41,
(void (interrupt far *)()) save_tbl
);
diskinfo.drive = changed_parms;
_bios_disk(0x09, &diskinfo); /* reset drive pair vector */
diskinfo.drive = changed_parms;
_bios_disk(0, &diskinfo); /* reset drive */
changed_parms = 0;
}
}
old_sector_size = sector_size;
fd_tbl = (DISK_TABLE far *) _dos_getvect(fixed_disk==DISK1 ? 0x46 : 0x41);
_numsecs = fd_tbl->fd_sec_per_track;
_shprod = _numsecs * fd_tbl->fd_heads;
boot_transfer(READ,0);
for(i=0; i<4; i++) {
if((part_data[i].sys_ind = master_boot_rec->ptable[i].sys_ind) != 0) {
part_data[i].s_cylinder=get_cyl(master_boot_rec->ptable[i].s_sec_cyl);
part_data[i].e_cylinder=get_cyl(master_boot_rec->ptable[i].e_sec_cyl);
boot_transfer(READ,i+1);
}
}
}
void
clean_quit()
{
struct diskinfo_t diskinfo;
if(changed_parms) {
_dos_setvect(changed_parms==DISK1 ? 0x46 : 0x41,
(void (interrupt far *)()) save_tbl
);
diskinfo.drive = changed_parms;
_bios_disk(0x09, &diskinfo); /* reset drive pair vector */
diskinfo.drive = changed_parms;
_bios_disk(0, &diskinfo); /* reset drive */
changed_parms = 0;
}
scr_sapage(start_page);
scr_smode(start_mode);
exit(0);
/* NOTREACHED */
}
int
make_fat(partno, fat_size, secs_in_rdir) /* make FAT (two copies) */
int partno,
fat_size;
word secs_in_rdir;
{
int i;
word *fatbuf, numsecs, offset, data_offset, secs_per_clus, secs_in_part;
byte *fatbuf2, *scratch;
BPB *bptr = &part_boot_rec[partno]->bpb;
dword relsec = master_boot_rec->ptable[partno].rel_sect;
extern word lineno;
numsecs = bptr->secs_in_fat;
data_offset = numsecs*2 + secs_in_rdir + bptr->res_sectors;
secs_in_part = bptr->nsectors;
secs_per_clus = (word) bptr->secs_per_au;
scratch = malloc(sector_size*secs_per_clus);
#ifdef DEBUG
printf("numsecs %d, offset %d, part_size %d\n",numsecs,data_offset,secs_in_part);
fflush(stdout);
#endif
if(!(fatbuf = (word *)calloc(numsecs,sector_size))) {
errno = ENOMEM;
return(0);
/* NOTREACHED */
}
fatbuf2 = (byte *)fatbuf;
if(fat_size == 12) {
fatbuf[0] = 0xfff8;
fatbuf[1] = 0x00ff;
}
else {
fatbuf[0] = 0xfff8;
fatbuf[1] = 0xffff;
}
/* get a list of sectors that can't be read -- presumably result of lo
* level formatting. Mark off appropriate cluster as bad.
*/
#ifndef DEBUG
scr_pos(lineno,42);
printf("Sector:");
for(offset=data_offset; offset <= secs_in_part; offset += secs_per_clus) {
word i;
i = (offset+secs_per_clus <= secs_in_part) ? secs_per_clus :
(secs_in_part-offset+1);
scr_pos(lineno,50);
printf("%u",offset-data_offset);
fflush(stdout);
if(dotrans(relsec,offset,scratch, i, READ)) {
/* got a bad sector */
word cnum = (offset - data_offset)/secs_per_clus + 2;
if(fat_size == 12) {
/* byte offset into cluster array is cnum*3/2 */
word *cptr = (word *)(fatbuf2 + ((cnum*3) >> 1));
*cptr |= (cnum & 1) ? 0xff70 : 0xff7;
}
else
fatbuf[cnum] = 0xfff7;
}
}
#endif
for(i=0; i<2; i++)
#ifndef DEBUG
if(dotrans(relsec,(i*numsecs)+1,fatbuf,numsecs,WRITE) < 0) {
errno = EINVAL;
return(0);
/* NOTREACHED */
}
#else
printf("Writing FAT, relsec 0x%lxL, whither 0x%x, count %d\n",
relsec,(i*numsecs)+1,numsecs);
fflush(stdout); (void) getch();
#endif
free(scratch);
free(fatbuf);
return(numsecs);
}
int
make_rdir(partno) /* make the root directory */
int partno;
{
int numsecs, offset;
word *buf, csize, temp;
BPB *bptr = &part_boot_rec[partno]->bpb;
dword relsec = master_boot_rec->ptable[partno].rel_sect;
offset = (bptr->secs_in_fat << 1) + 1;
numsecs = (bptr->nroot_ents+15)/16;
csize = (word) bptr->secs_per_au;
if((temp = numsecs % csize) != 0)
numsecs += csize-temp;
if((buf = (word *)calloc(numsecs,sector_size)) == NULL) {
errno = ENOMEM;
return(0);
/* NOTREACHED */
}
#ifndef DEBUG
if(dotrans(relsec,offset,buf,numsecs, WRITE) < 0) {
errno = EINVAL;
return(0);
/* NOTREACHED */
}
#else
printf("Writing directory, relsec (long) 0x%lx, whither 0x%x, count %d\n", relsec,offset,numsecs);
fflush(stdout); getch();
#endif
free(buf);
return(numsecs);
}
#ifdef BT_IN_C
void
boot_transfer(op, idx)
word op, /* either READ or WRITE */
idx; /* 0=master boot record, 1-5=partition */
{
union REGS fregs;
struct SREGS segreg;
if(idx) {
PARTITION *pptr;
pptr = & master_boot_rec->ptable[--idx];
fregs.x.bx = (unsigned) part_boot_rec[idx];
segreg.es = FP_SEG(part_boot_rec[idx]);
fregs.x.cx = pptr->s_sec_cyl; /* cylinder 0, sector 1 */
fregs.h.dh = pptr->s_head; /* head 0 */
}
else {
fregs.x.bx = (unsigned) master_boot_rec;
segreg.es = FP_SEG(master_boot_rec);
fregs.x.cx = 0x0001; /* cylinder 0, sector 1 */
fregs.h.dh = 0; /* head 0 */
}
fregs.h.ah = op; /* what to do */
fregs.h.al = 1; /* do 1 sector */
fregs.h.dl = fixed_disk;
int86x(0x13,&fregs,&fregs,&segreg);
}
#endif