home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.update.uu.se
/
ftp.update.uu.se.2014.03.zip
/
ftp.update.uu.se
/
pub
/
rainbow
/
msdos
/
decus
/
RB139
/
rx50-103.lzh
/
RX50INIT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1986-09-10
|
8KB
|
346 lines
/*t RX50INIT -- Initialize RX50 MS-DOS Data Diskette */
/*----------------------------------------------------------------------*/
/* */
/* RX50INIT -- Initialize RX50 MS-DOS Data Diskette */
/* */
/*----------------------------------------------------------------------*/
#define PROGREV "[1.03]" /* 09-Dec-84 14:00 */
/* Copyright (c) 1984 by Robert F. Morse
** 17 Bowdoin Street
** Cambridge, MA 02138
**
**
** Function: Initialize the directory and FAT of an RX50 diskette to
** be used as an MS-DOS data diskette for a DECmate or Rainbow.
**
** Invocation:
**
** RX50INIT [d:] [volume-name]
**
** The drive letter is optional; D is the default. The volume name
** is optional; if none is given, none is written in the directory.
**
** Notes: This version is for an IBM PC-AT and requires that device
** driver RX50DRVR.SYS be loaded when the system was booted. This
** driver maps references to drive D: to the AT's high-capacity drive
** (normally drive A:) and sets that drive to handle the 80-track
** 10-sector RX50 format.
*/
#include "standard.h"
#include "msdosdir.h"
#include "msdosdpb.h"
#define SECTOR_SIZE 512
#define FAT_SECTORS 3
#define FAT_BUFSIZE (FAT_SECTORS * SECTOR_SIZE)
#define FAT_START_1 20
#define FAT_START_2 23
#define CLUSTER_EOF 0x0FFF
#define CLUSTER_MEDIA 0x0FFA
#define DIR_SECTORS 6
#define DIR_BUFSIZE (DIR_SECTORS * SECTOR_SIZE)
#define DIR_START 26
#define DPB_MEDIA 0xFA
#define DPB_MAX_CLUSTER 769
char *malloc();
/*^---------- Global Constants & Data -------------*/
char *fatbuf;
MSDOS_Dir *dirbuf;
char vol_name[12] = " ";
uint target_unit = 3; /* default drive is D: */
char *disk_errs[] ={ "Write protect", /* 0 */
"Invalid unit", /* 1 */
"Not ready", /* 2 */
"Bad command", /* 3 */
"Data CRC", /* 4 */
"Bad request", /* 5 */
"Seek", /* 6 */
"Unknown media", /* 7 */
"Sector not found", /* 8 */
"Out of paper", /* 9 */
"Write fault", /* 10 */
"Read fault", /* 11 */
"I/O", /* 12 */
"", /* 13 */
"", /* 14 */
"Invalid disk change"}; /* 15 */
/* BOOT BLOCK, to be written in block 0 */
struct {byte jump[3];
char oem_name[8];
int bytes_sector;
byte sects_alu;
int reserved_sects;
byte num_fats;
int num_dirents;
int total_sectors;
byte fat_id;
int fat_sectors;
int sects_track;
int num_heads;
int hidden_sects; } boot_block = {
{0xE9, 0x00, 0x00},
{'D', 'E', 'C', '-', 'R', 'X', '5', '0'},
512, 1, 20, 2, 96, 800, 0xFA, 3,
10, 1, 0 };
/*^*/
#define DOS_GETDATE 0x2A
#define DOS_GETTIME 0x2C
typedef struct {
unsigned Wyr;
unsigned Wmo;
unsigned Wda;
unsigned Whr;
unsigned Wmn;
unsigned Wsc;
unsigned Whn;
unsigned Wdw;
} When;
When now;
timestamp (w) When *w;
{
RuptRegs reg;
getsegs (®);
doscall (DOS_GETDATE, ®);
w->Wyr = reg.w.cx;
w->Wmo = reg.b.dh;
w->Wda = reg.b.dl;
w->Wdw = reg.b.al;
doscall (DOS_GETTIME, ®);
w->Whr = reg.b.ch;
w->Wmn = reg.b.cl;
w->Wsc = reg.b.dh;
w->Whn = reg.b.dl;
}
/*^------------------------------------------------------------*/
write_sect (unit, block, count, buffer) char *buffer;
/*---------------------------------------------------------------
** Write <count> sectors beginning with sector <block> on <unit>
** from <*buffer>, returning 0 if OK or aborting the program if
** there is an uncorrectable error.
*/
#define MSDOS_WRITE 0x26
#define CF_MASK 0x0001
{ RuptRegs reg;
char ch;
again:
getsegs (®);
reg.w.ax = unit;
reg.w.bx = (uint) buffer;
reg.w.cx = count;
reg.w.dx = block;
if (intcall (MSDOS_WRITE, ®) & CF_MASK)
{
cputf ("\n\n%s error writing drive %c:\nAbort, Retry? ",
disk_errs[reg.b.al], unit + 'A');
do ch = cgetcne();
while (strchr ("AaRr\003", ch) == NULL);
cputc ('\n');
if (toupper (ch) == 'R')
goto again;
cputs ("CANCELLED");
_exit (1);
}
else
return (0);
}
get_fat (fat, n) char *fat;
{ int w;
w = * (int*) &fat[(n*3)/2];
if (n & 1)
w >>= 4;
return(w & 0x0FFF);
}
put_fat (fat, n, val) char *fat;
{ int *w;
w = (int*) &fat[(n*3)/2];
if (n & 1)
*w = (*w & 0x000F) | ((val << 4) & 0xFFF0);
else
*w = (*w & 0xF000) | (val & 0xFFF);
}
/*^-----------------------------------*/
main (argc, argv) char *argv[];
/*------------------------------------*/
{ int n, x, y, err;
char ch;
MSDOS_Dir *p;
MSDOS_Dpb dpb;
RuptRegs reg;
unsigned int attr;
unsigned int clus;
cputf ("%-45.45s%10.10s%24.24s\n%79.79s",
"Initialize DEC RX50 Data Diskette",
PROGREV,
"Copyright (c) 1984",
"by Robert F. Morse");
n = 1;
/*
** Get the drive letter (if any) from the command arguments.
*/
if (n < argc)
{
if (argv[n][1] == ':')
{
if ( ((target_unit = toupper (argv[n][0]) - 'A') < 25) &&
(strlen (argv[n]) == 2) )
++n;
else
{
cputf ("\n INVALID SOURCE DRIVE LETTER %s", argv[n]);
_exit (1);
}
}
}
/*
** Get the volume name (if any) from the command arguments.
*/
if (n < argc)
{
for (x = 0; x < 11; ++x)
{
if ((ch = argv[n][x]) == '\0')
break;
if (isalnum (ch) || (ch == '-'))
vol_name[x] = toupper (ch);
else
{
cputf ("\n INVALID CHARACTER '%c' IN VOLUME NAME %s", ch, argv[n]);
_exit (1);
}
}
}
/*
** Allocate memory for disk data buffers.
*/
if ( ((fatbuf = malloc(FAT_BUFSIZE)) == NULL) ||
((dirbuf = (MSDOS_Dir*) malloc(DIR_BUFSIZE)) == NULL) )
{
cputs( "\n INSUFFICIENT MEMORY");
_exit(1);
}
/*
** Ask the operator to insert a diskette in the target drive.
*/
cputf(
"\n Insert diskette into drive \033[7m %c \033[m and press ENTER ",
target_unit + 'A');
do {
ch = cgetcne ();
if (ch == 3) /* quit on ctrl/C */
{
cputf ("\nCANCELLED");
_exit (1);
}
} while (ch != '\r');
/*
** Get the diskette's DPB to check that it is a possible RX50 and is NOT
** (horrors!) the hard disk. Also catches uninstalled drive letters.
*/
reg.b.dl = target_unit + 1;
doscall (0x32, ®);
if (reg.b.al)
{
cputf ("\n DRIVE %c: NOT INSTALLED", target_unit + 'A');
_exit (1);
}
peek (reg.w.ds, reg.w.bx, &dpb, sizeof(dpb));
if ((dpb.Dpb_max_cluster != DPB_MAX_CLUSTER) ||
(dpb.Dpb_media != DPB_MEDIA) )
{
cputf ("\n DRIVE %c: CANNOT HANDLE RX50 DISKETTES", target_unit + 'A');
_exit (1);
}
/*
** Set up and write the FAT.
**
** Note: This first attempt to write is on cylinder 2, which will fail
** with a sector-not-found if a 48-tpi diskette is in the drive.
*/
setmem (fatbuf, FAT_BUFSIZE, 0x00);
put_fat (fatbuf, 0, CLUSTER_MEDIA);
put_fat (fatbuf, 1, CLUSTER_EOF);
write_sect (target_unit, FAT_START_1, FAT_SECTORS, fatbuf);
write_sect (target_unit, FAT_START_2, FAT_SECTORS, fatbuf);
/*
** Set up and write the directory.
*/
setmem (dirbuf, DIR_BUFSIZE, 0x00);
timestamp (&now);
if (vol_name[0] != ' ')
{
p = dirbuf;
memcpy (p->Dir_name, vol_name, 11);
p->Dir_attr = Dirattr_VOL;
p->Dir_date.Dt_yr = now.Wyr - 1980;
p->Dir_date.Dt_mo = now.Wmo;
p->Dir_date.Dt_da = now.Wda;
p->Dir_time.Dt_hr = now.Whr;
p->Dir_time.Dt_mn = now.Wmn;
p->Dir_time.Dt_sc = now.Wsc / 2;
}
write_sect (target_unit, DIR_START, DIR_SECTORS, dirbuf);
/*
** Write the boot block in block 0.
*/
setmem (fatbuf, SECTOR_SIZE, 0x00);
memcpy (fatbuf, &boot_block, sizeof (boot_block));
write_sect (target_unit, 0, 1, fatbuf);
/*
** Write an all-zero sector in block 1 (the IBM FAT position).
*/
setmem (fatbuf, SECTOR_SIZE, 0x00);
write_sect (target_unit, 1, 1, fatbuf);
/*
** Write an all-zero sector in block 10 to forstall any attempted DECmate boot
*/
write_sect (target_unit, 10, 1, fatbuf);
/*
** Done--announce success and exit.
*/
cputs ("\n Diskette initialized");
if (vol_name[0] != ' ')
cputf (", volume name is %s", vol_name);
_exit (0);
}
/******/