home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
f
/
ftp-102.zip
/
ftape-1.02
/
driver
/
userft.c
< prev
Wrap
C/C++ Source or Header
|
1992-10-12
|
10KB
|
423 lines
/* User code for floppytape.
Copyright (C) 1992 David L. Brown, Jr.
This program 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.
This program 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 this program; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* userft.c,v 1.14 1992/10/13 01:45:08 dbrown Exp
*
* userft.c,v
* Revision 1.14 1992/10/13 01:45:08 dbrown
* Added FSF copyright.
*
* Revision 1.13 1992/10/12 05:13:33 dbrown
* Added ioctl to set drive data rate.
*
* Revision 1.12 1992/10/10 07:02:09 dbrown
* Made write stream.
*
* Revision 1.11 1992/10/10 03:19:38 dbrown
* Added write error handling so that errors and their location can be
* passed back to the user.
*
* Revision 1.10 1992/10/09 05:53:44 dbrown
* Read is reliable. Write is flaky and can't handle errors.
*
* Revision 1.9 1992/10/09 01:29:22 dbrown
* Write now streams and works somewhat robustly. One little possible
* crashing position left.
*
* Revision 1.8 1992/10/09 00:36:15 dbrown
* Initial writing of full write. Untested.
*
* Revision 1.7 1992/10/08 23:45:24 dbrown
* Read now does a copyout instead of using mapped buffers. Before, read
* didn't have any control of when the user would actually get the data
* out of the buffer. If the user delayed, then that data could be
* overwritten with the read from tape.
*
* Revision 1.6 1992/10/08 23:29:28 dbrown
* Performs streaming reliable reads.
*
* Revision 1.5 1992/10/08 04:52:42 dbrown
* First attempt to add streaming read. Doesn't really work and panics
* periodically.
*
* Revision 1.4 1992/10/04 23:10:14 dbrown
* Added facilities for performing seek test.
*
* Revision 1.3 1992/10/04 21:46:01 dbrown
* Now supports non-streaming, single sector reads.
*
* Revision 1.2 1992/10/03 23:56:40 dbrown
* Moved enough of the old driver into the new to get drive status, and
* seek the tape and the tape head.
*
* Revision 1.1 1992/10/03 22:54:02 dbrown
* Copied from old driver.
*/
#include <stdio.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "fdtape-io.h"
void run (int fd);
void read_many (int fd);
main (int argc, char **argv)
{
int fd;
char *name;
#if 0
char *data;
#endif
int done = 0;
int status, result;
struct fdt_error error;
struct _fdt_id id;
int value;
int is_tty = 1;
struct write_cease wc;
if (argc < 2)
name = "/dev/ftape";
else
{
name = argv[1];
if (argc >= 2)
is_tty = 0;
}
fd = open (name, O_RDWR);
if (fd < 0)
{
perror ("Opening tape");
exit (1);
}
run (fd);
#if 0
/* Map the tape buffer. */
data = (char *) malloc (65536);
if (mmap (data, 65536,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0) < 0)
perror ("Can't map tape buffer"), exit (1);
#endif
printf ("h for Help\n");
while (!done)
{
char cmd[80];
printf ("--> ");
gets (cmd); /* Yuck. */
if (!is_tty)
puts (cmd), fflush (stdout);
switch (*cmd)
{
case 'h':
printf ("s - Status e - Error\n");
printf ("B - Beginning of tape E - End of tape.\n");
printf ("fn - forward n segments rn - reverse n segments\n");
printf ("<n m - read m segments starting at n\n");
printf (">n m - write m segments starting at m\n");
printf ("# - Submit error map I - Read id\n");
printf ("Sn - Seek to track. @n - Set data rate to n bps.\n");
/*
e - Error\n\
B - Beginning of tape.\n\
E - End of tape.\n\
fn - Forward n segments.\n\
rn - Reverse n segments.\n\
t - Stop tape.\n\
R - Reset tape drive.\n\
F - Logical forward.\n\
P - Pause.\n\
Sn - Seek to track.\n\
I - Read id.\n\
M - Read many ids.\n\
# - Submit an error map (causes sync)\n\
<n - Read segment n\n
*/
printf ("Q - Quit\n");
break;
case 's':
result = ioctl (fd, FDT_REPORT_STATUS, &status);
if (result != 0)
perror ("report drive status");
else
printf ("Status = 0x%x\n", status);
break;
case 'e':
result = ioctl (fd, FDT_REPORT_ERROR_CODE, &error);
if (result != 0)
perror ("report drive error");
else
{
printf ("Error = 0x%x (command = %d)\n", error.error,
error.command);
}
break;
case 'B':
result = ioctl (fd, FDT_SEEK_TO_BEGINNING, 0);
if (result != 0)
perror ("Seek to beginning");
break;
case 'E':
result = ioctl (fd, FDT_SEEK_TO_END, 0);
if (result != 0)
perror ("Seek to end");
break;
case 'f':
value = atoi (&cmd[1]);
result = ioctl (fd, FDT_SEEK_FORWARD, &value);
if (result != 0)
perror ("Seek forward");
break;
case 'r':
value = atoi (&cmd[1]);
result = ioctl (fd, FDT_SEEK_REVERSE, &value);
if (result != 0)
perror ("Seek backward");
break;
case '@':
value = atoi (&cmd[1]);
result = ioctl (fd, FDT_SET_DATA_RATE, &value);
if (result != 0)
perror ("Select data rate");
break;
case 'I':
{
struct _fdt_find_me fm;
fm.segment = 0;
result = ioctl (fd, FDT_FIND_ME, &fm);
printf ("result = %d, actual = %d\n",
result, fm.actual_segment);
}
break;
#if 0
case 't':
result = ioctl (fd, FDT_STOP_TAPE, 0);
if (result != 0)
perror ("Stop tape");
break;
case 'R':
result = ioctl (fd, FDT_RESET, 0);
if (result != 0)
perror ("Reset tape drive");
break;
case 'F':
result = ioctl (fd, FDT_LOGICAL_FORWARD, 0);
if (result != 0)
perror ("Logical forward");
break;
case 'P':
result = ioctl (fd, FDT_PAUSE, 0);
if (result != 0)
perror ("Pause");
break;
#endif
case 'S':
value = atoi (&cmd[1]);
result = ioctl (fd, FDT_SEEK_TO_TRACK, &value);
if (result != 0)
perror ("Seek to track");
break;
#if 0
case 'I':
result = ioctl (fd, FDT_READ_ID, &id);
if (result != 0)
perror ("Read id.");
else
{
printf ("ID: cylinder = %d, head = %d, sector = %d\n",
id.cylinder, id.head, id.sector);
}
break;
#endif
case '#':
{
struct error_map emap;
unsigned long error_masks[150];
bzero (error_masks, 150 * sizeof (unsigned long));
emap.count = 150;
emap.error_masks = error_masks;
result = ioctl (fd, FDT_SUBMIT_ERROR_MAP, &emap);
if (result != 0)
{
perror ("Cannot submit error map");
exit (1);
}
}
break;
case '>':
{
int fdi;
struct tape_write tw;
char buffer[32768];
int count;
sscanf (&cmd[1], "%d%d", &tw.segment,
&count);
fdi = open ("INPUT", O_RDONLY);
if (fdi < 0)
{
perror ("Can't open input\n");
break;
}
tw.buffer = buffer;
while (count > 0)
{
result = read (fdi, buffer, 32768);
if (result != 32768)
{
perror ("Can't read");
continue;
}
result = ioctl (fd, FDT_WRITE, &tw);
printf ("Write result = %d, (%d), error on %d\n", result,
tw.actual_segment, tw.error_location);
if (result != 0)
perror ("");
#if 0
printf (" ++] ");
getchar ();
#endif
tw.segment++;
count--;
}
result = ioctl (fd, FDT_CEASE_WRITING, &wc);
if (result != 0)
perror ("Ceasing");
printf ("Ceased actual_segment = %d, error on %d\n",
wc.actual_segment, wc.error_location);
close (fdi);
}
break;
case '<':
{
int fdo;
struct tape_read tr;
char buffer[32768];
tr.buffer = buffer;
sscanf (&cmd[1], "%d%d", &tr.segment,
&tr.count);
fdo = open ("OUTPUT", O_WRONLY | O_TRUNC | O_CREAT,
0666);
if (fdo < 0)
perror ("Can't create OUTPUT"), exit (1);
while (tr.count > 0)
{
result = ioctl (fd, FDT_READ, &tr);
if (result < 0)
perror ("Read error");
result = write (fdo, buffer, 32768);
if (result != 32768)
perror ("Can't write");
printf ("actual = %d, buffer = %d, error_bits = 0x%08x\n",
tr.actual_segment,
tr.buffer,
tr.error_bits);
#if 0
printf (" ++] ");
getchar ();
#endif
tr.segment++;
tr.count--;
}
}
break;
case 'Q':
done = 1;
break;
default:
printf ("Unknown command\n");
break;
}
}
close (fd);
}
void
run (int fd)
{
int status;
struct fdt_error error;
int result;
result = ioctl (fd, FDT_REPORT_STATUS, &status);
if (result != 0)
perror ("report drive status");
else
printf ("status = 0x%x\n", status);
result = ioctl (fd, FDT_REPORT_ERROR_CODE, &error);
if (result != 0)
perror ("report error");
else
printf ("error = 0x%x, command = 0x%x\n", error.error,
error.command);
#if 0
result = ioctl (fd, FDT_REPORT_CONFIGURATION, &status);
if (result != 0)
perror ("report drive configuration");
else
printf ("configuration = 0x%x\n", status);
result = ioctl (fd, FDT_REPORT_ROM_VERSION, &status);
if (result != 0)
perror ("report rom version");
else
printf ("rom version = 0x%x\n", status);
result = ioctl (fd, FDT_REPORT_VENDOR_ID, &status);
if (result != 0)
perror ("report vendor id");
else
printf ("vendor id = 0x%x\n", status);
#endif
}
#if 0
void
read_many (int fd)
{
struct _fdt_id ids[5000];
int count, i, done = 0;
int result;
for (count = 0; count < 5000 && !done; count++)
{
result = ioctl (fd, FDT_READ_ID, &ids[count]);
if (result != 0)
done = 1;
}
for (i = 0; i < count; i++)
{
printf ("%d %d %d\n", ids[i].cylinder,
ids[i].head, ids[i].sector);
}
}
#endif