home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1999 mARCH
/
PCWK3A99.iso
/
Archiwiz
/
Tar320
/
SOURCES.ZIP
/
DISK.C
< prev
next >
Wrap
Text File
|
1994-08-23
|
10KB
|
332 lines
/* disk.c - MS-DOS diskette service for Tar program (see file tar.c)
* Author: T.V.Shaporev
* Prepared for release 19 Oct 1990
*
* Called by readtape(), writetape() etc. - see file tape.c
*/
#include "sysup.h"
#ifdef __TURBOC__
#include <string.h>
#include <stdio.h>
#include <dos.h>
#include "modern.h"
#include "define.h"
#define QUADISK '\200'
#define RAINBOW '\201'
#define SMT '\x18' /* Set Media Type */
extern int diskserv __ARGS__((int, int, int, int, int, int, void far *));
extern void far *diskspec __ARGS__((int, int, int, int, int,
struct BYTEREGS far *));
extern void printbs __ARGS__(( int ));
static void errdisk __ARGS__(( int ));
static void redrive __ARGS__(( void ));
static int trydisk __ARGS__(( int, char *, int ));
static void nextdisk __ARGS__(( void ));
static void skipsect __ARGS__(( void ));
static void ibmdisk __ARGS__(( int, char *, int ));
static void rainbow __ARGS__(( int, char *, int ));
#define FDC_STATUS (*(char far *)0x0490L)
static unsigned short heads, tracks, sectors, last_seg, this_seg;
static char calibr = 0;
struct { char type_disk[16]; unsigned size, heads, tracks, sectors; }
ftab[] = { {"fd048ss8", 160, 1, 40, 8 },
{"fd048ss9", 180, 1, 40, 9 },
{"fd048ds8", 320, 2, 40, 8 },
{"fd048ds9", 360, 2, 40, 9 },
{"fd135ds9", 720, 2, 80, 9 },
{"fd096ds9", 720, 2, 80, 9 },
{"fd096ds15", 1200, 2, 80, 15 },
{"fd135ds18", 1440, 2, 80, 18 },
{"", 2880, 2, 80, 36 } };
static void errdisk(n)
int n;
{
register int i;
static struct { unsigned char code; char *text; } errtab[] = {
{ 0, "undefined error" },
{ 0x00, "no error on last operation" },
{ 0x01, "invalid request to controller" },
{ 0x02, "bad address mark" },
{ 0x03, "write protect" },
{ 0x04, "sector ID bad or not found" },
{ 0x05, "reset failed" },
{ 0x06, "floppy changed line on" },
{ 0x08, "DMA failure" },
{ 0x09, "DMA overrun: attempted to write across 64K" },
{ 0x0b, "bad track flag encountered" },
{ 0x0C, "media type not found" },
{ 0x10, "bad CRC: invalid CRC when data checked" },
{ 0x11, "recoverable error found; data corrected" },
{ 0x20, "controller failure" },
{ 0x40, "bad seek; requested track not found" },
{ 0x80, "time out; drive did not respond" },
{ 0xff, "sense operation failed" } };
for (i=1; errtab[i].code!=n && i<dimof(errtab); i++) ;
if (i>=dimof(errtab)) i = 0;
fprintf(myout, "Tar: diskette error: %s\n", errtab[i].text);
}
int argdisk(k)
register k;
{
register i;
for (i=0; ftab[i].size!=k && i<dimof(ftab); i++) ;
if (i >= dimof(ftab)) return -1;
sectors = ftab[i].sectors;
tracks = ftab[i].tracks;
heads = ftab[i].heads;
return 0;
}
int defdev(k)
register char *k;
{
register i;
for (i=0; i<dimof(ftab); i++) {
if (ftab[i].type_disk[0]!=0 && stricmp(ftab[i].type_disk, k)==0)
goto found;
}
if (stricmp("rainbow", k) == 0) {
calibr = RAINBOW;
sectors = 10;
tracks = 80;
heads = 1;
return 0;
}
return -1;
found:
sectors = ftab[i].sectors;
tracks = ftab[i].tracks;
heads = ftab[i].heads;
return 0;
}
static void redrive() /* reset & recalibrate drive */
{
(void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
if (calibr & QUADISK) {/* Init 800 */
FDC_STATUS = 0x61; /* FDC status buts <- 61h - ??? */
/* verify Track 0 Sector 1 Side 0 */
(void)diskserv(4, ndrive, 0, 0, 1, 1, NULL);
/* verify Track 1 Sector 1 Side 0 */
(void)diskserv(4, ndrive, 0, 1, 1, 1, NULL);
(void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
FDC_STATUS = 0x54; /* FDC status buts <- 54h - ??? */
} else if (calibr == SMT) {
struct BYTEREGS b;
(void)diskspec(SMT, ndrive, heads-1, tracks-1, sectors, &b);
} else if (calibr != 0) {
(void)diskserv(0x17, ndrive, 0, 0, 1, calibr, NULL);
}
}
void inidisk(void)
{
register j, k;
unsigned tb;
struct BYTEREGS b;
short maxhead, maxtrack, maxsect;
static unsigned short sizelist[5] = {
/* 360K, 720K, 1.2M, 1.44M, 2.88M */
720, 1440, 2400, 2880, 5760
};
static unsigned char ctable[5][5] = {
/* Media size: 360K, 720K, 1.2M, 1.44M, 2.88M */
/* 2.88M drive */ {2, SMT, SMT, SMT, 0},
/* 1.44M drive */ {2, SMT, SMT, 0, 0},
/* 1.2M drive */ {2, QUADISK, 3, 0, 0},
/* 720K drive */ {2, 4, 0, 0, 0},
/* old drive */ {1, 0, 0, 0, 0},
};
if (!calibr) {
/* reset drive */
(void)diskserv(0, ndrive, 0, 0, 1, 1, NULL);
/* get drive params (set default to 2x40x9) */
(void)diskspec(8, ndrive, 1, 39, 9, &b);
maxhead = b.dh + 1;
maxtrack = b.ch + ((unsigned)(b.cl & 0xC0) << 2) + 1;
maxsect = b.cl & 0x3f;
if ((tb = maxhead * maxtrack * maxsect) == 0) {
fprintf(stderr, "Tar: drive not present\n");
done(ERINIT);
}
if (!k_flag) {
sectors = maxsect; tracks = maxtrack; heads = maxhead;
if (v_flag) fprintf(myout, "Diskette capacity %uK assigned\n", tb/2);
}
last_seg = sectors*tracks*heads;
if (last_seg == 2*2880 && tb == 2*2880) {
/* I don't know 2.88M drive geometry, so use parameters got */
sectors = maxsect; tracks = maxtrack; heads = maxhead;
}
for (j=dimof(sizelist)-1; j && sizelist[j] != tb; j--);
for (k=dimof(sizelist)-1; k && sizelist[k]<last_seg; k--);
calibr = ctable[j][k];
}
this_seg = 0;
redrive();
/* get drive error status */
k = diskserv(1, ndrive, 0, 0, 1, 1, NULL);
if (k!=0 && k!=6) {
errdisk(k);
if (k!=0x11) done(ERINIT);
}
if (!cblock) {
/* Some BIOSes do strange things on quad drives. */
/* I guess they loose info while read or write through 9th to */
/* 10th sector. I hope, the following solves the problem. */
printbs(cblock = a_flag ? 1 : (sectors < 9 ? sectors : 3));
}
}
static int trydisk(wr, buf, bl)
int wr, bl;
char *buf;
{
int i, k;
register short s, h, t;
s = this_seg % sectors + 1; /* sector */
t = this_seg / sectors;
h = t % heads; /* head */
t /= heads; /* track */
i = 0;
do {
k = diskserv((wr ? 3 : 2), ndrive, h, t, s, bl, buf);
#if 0
if (!k && wr) {/* verify */
char chk[NBLOCK*BLKSIZE];
k = diskserv(4, ndrive, h, t, s, bl, buf);
}
#endif
if (k) redrive();
} while (k && ++i<3);
if (cbreak) done(0);
if (k == 0 || k == 0x11) {
k = 0;
} else if (k!=0x02 && k!=0x04 && k!=0x0B && k!=0x10 && k!=0x40) {
errdisk(k); /* fatal error */
if (!i_flag || wr) done(wr ? EWRITE : ERREAD);
}
return k;
}
static void nextdisk()
{
fprintf(stderr, "Tar: insert NEXT diskette and press ENTER when ready...");
(void)yes_no('\0');
this_seg = 0;
redrive();
}
static void skipsect()
{
fprintf(myout, "Tar: warning: bad sector %d, skipped\n", this_seg);
}
static void ibmdisk(wr, buf, bl)
int wr, bl;
char *buf;
{
int i, j, k;
i = sectors - this_seg % sectors;
if (i > bl) i = bl;
while (bl > 0) {
if (this_seg >= last_seg) nextdisk();
if ((k = trydisk(wr, buf, i)) == 0) {
this_seg += i;
buf += i*BLKSIZE;
bl -= i;
} else {
for (j=0; j<i; j++) {
if (i>1) k = trydisk(wr, buf, 1);
if (k == 0) { /* one sector o'k */
buf += BLKSIZE;
--bl;
} else skipsect();
++this_seg;
}
}
i = sectors < bl ? sectors : bl;
}
}
static void rainbow(wr, buf, bl)
int wr, bl;
char *buf;
{
int i, j, k, n;
static char e85tab[50] = {
/* x = 0 1 2 3 4 5 6 7 8 9 */
/* 0x */ 1, 3, 5, 7, 9, 2, 4, 6, 8, 10,
/* 1x */ 3, 5, 7, 9, 1, 4, 6, 8, 10, 2,
/* 2x */ 5, 7, 9, 1, 3, 6, 8, 10, 2, 4,
/* 3x */ 7, 9, 1, 3, 5, 8, 10, 2, 4, 6,
/* 4x */ 9, 1, 3, 5, 7, 10, 2, 4, 6, 8,
};
while (bl > 0) {
if (this_seg >= last_seg) nextdisk();
i = (this_seg/10 + 1) % 80; /* track */
j = e85tab[this_seg%50]; /* sector */
n = 0;
do {
k = diskserv((wr?3:2), ndrive, 0, i, j, 1, buf);
if (k && ++n<3) redrive();
} while (k && n<3);
if (cbreak) done(0); /* ??? */
if (!k) { buf += BLKSIZE; --bl; } else skipsect();
++this_seg;
}
}
/* Interface routines */
int dread(buf, n)
char *buf; register n;
{
register k = n / BLKSIZE;
if (n % BLKSIZE) return -1;
if (calibr == RAINBOW) rainbow(0, buf, k); else ibmdisk(0, buf, k);
return n;
}
int dwrite(buf, n)
char *buf; register n;
{
n = (BLKSIZE-1 + n) / BLKSIZE;
if (calibr == RAINBOW) rainbow(1, buf, n); else ibmdisk(1, buf, n);
return BLKSIZE*n;
}
int dback(n)
register n;
{
this_seg = this_seg > n ? this_seg-n : 0;
return n;
}
#endif