home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
disk
/
Misc
/
dd
/
dev.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-02
|
12KB
|
413 lines
/*
* dev.c - device manipulation functions
*
* Bruno Costa - 30 Nov 91 - 2 Jun 92
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/errors.h>
#include <devices/trackdisk.h>
#include <dos/dos.h>
#include <dos/filehandler.h>
#include <dos/dosextens.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <string.h>
#include "dossupport.h"
#include "dev.h"
extern struct Library *DOSBase;
extern struct Library *SysBase;
extern int quiet;
static int blocksize = 512;
static int sectorsize = 512;
static unsigned char *sectorbuf = NULL;
int devblocksize (void)
{
return blocksize;
}
int devsectorsize (void)
{
return sectorsize;
}
void Motor (struct IOExtTD *disk, int onoff)
{
disk->iotd_Req.io_Length = onoff;
disk->iotd_Req.io_Command = TD_MOTOR;
DoIO ((struct IORequest *) disk);
}
int secread (struct IOExtTD *disk, long int offset)
{
disk->iotd_Req.io_Length = sectorsize;
disk->iotd_Req.io_Data = (APTR) sectorbuf;
disk->iotd_Req.io_Command = CMD_READ;
disk->iotd_Req.io_Offset = (ULONG) (offset * sectorsize);
DoIO ((struct IORequest *) disk);
return (disk->iotd_Req.io_Error == 0);
}
int secwrite (struct IOExtTD *disk, long int offset)
{
disk->iotd_Req.io_Length = sectorsize;
disk->iotd_Req.io_Data = (APTR) sectorbuf;
disk->iotd_Req.io_Command = CMD_WRITE;
disk->iotd_Req.io_Offset = (ULONG) (offset * sectorsize);
DoIO ((struct IORequest *) disk);
return (disk->iotd_Req.io_Error == 0);
}
int devread (struct IOExtTD *diskreq, BPTR f, long int skip, long int count)
{
int secskip = skip / sectorsize;
int byteskip = skip - (secskip * sectorsize);
int seccount = (count + byteskip + sectorsize - 1) / sectorsize;
int bytecount = (seccount * sectorsize) - count - byteskip;
int sec;
for (sec = 0; sec < seccount; sec++)
{
if (CheckSignal (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D))
return RETURN_FAIL;
if (!secread (diskreq, secskip + sec))
return (diskreq->iotd_Req.io_Error);
if (seccount == 1)
{
if (Write (f, sectorbuf + byteskip, sectorsize - byteskip - bytecount) != sectorsize - byteskip - bytecount)
return IoErr ();
}
else if (sec == 0)
{
if (Write (f, sectorbuf + byteskip, sectorsize - byteskip) != sectorsize - byteskip)
return IoErr ();
}
else if (sec == seccount - 1)
{
if (Write (f, sectorbuf, sectorsize - bytecount) != sectorsize - bytecount)
return IoErr ();
}
else
{
if (Write (f, sectorbuf, sectorsize) != sectorsize)
return IoErr ();
}
if (!quiet)
{
Printf (" %ld/%ld\r", sec + 1, seccount);
Flush (Output ());
}
}
return 0;
}
int devwrite (BPTR f, struct IOExtTD *diskreq, long int skip, long int count)
{
/*
* devwrite() is a bit more complicated than devread() because partially
* skipped sectors should not be zeroed -- these sectors have to be read
* first, then partially filled with data from the file and then at last
* written to the device. The secskip/byteskip/seccount/bytecount
* calculations are probably the same as in devread().
*/
int secskip = skip / sectorsize;
int byteskip = skip - (secskip * sectorsize);
int seccount = (count + byteskip + sectorsize - 1) / sectorsize;
int bytecount = (seccount * sectorsize) - count - byteskip;
int sec;
for (sec = 0; sec < seccount; sec++)
{
if (CheckSignal (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D))
return RETURN_FAIL;
if (seccount == 1)
{
if (!secread (diskreq, secskip + sec))
return (diskreq->iotd_Req.io_Error);
if (Read (f, sectorbuf + byteskip, sectorsize - byteskip - bytecount) != sectorsize - byteskip - bytecount)
return IoErr ();
}
else if (sec == 0)
{
if (!secread (diskreq, secskip + sec))
return (diskreq->iotd_Req.io_Error);
if (Read (f, sectorbuf + byteskip, sectorsize - byteskip) != sectorsize - byteskip)
return IoErr ();
}
else if (sec == seccount - 1)
{
if (!secread (diskreq, secskip + sec))
return (diskreq->iotd_Req.io_Error);
if (Read (f, sectorbuf, sectorsize - bytecount) != sectorsize - bytecount)
return IoErr ();
}
else
{
if (Read (f, sectorbuf, sectorsize) != sectorsize)
return IoErr ();
}
if (!secwrite (diskreq, secskip + sec))
return (diskreq->iotd_Req.io_Error);
if (!quiet)
{
Printf (" %ld/%ld\r", sec + 1, seccount);
Flush (Output ());
}
}
return 0;
}
#define NDEVTYPES 10
#define devtype(code) (((code) < NDEVTYPES) ? devtypetable[code] : "Unknown")
void devinfo (char *dosname, char *execname,
struct FileSysStartupMsg *fss, struct DosEnvec *de,
struct Device *dev, struct DriveGeometry *geo)
{
static char *devtypetable[NDEVTYPES] = {
"Direct Access",
"Sequential Access",
"Printer",
"Processor",
"Worm",
"CD-ROM",
"Scanner",
"Optical Disk",
"Medium Changer",
"Communication"
};
static struct {int offset; char *format;} table[] = {
{DE_BOOTPRI, " Boot Priority: %ld\n"},
{DE_DOSTYPE, " Filesystem: 0x%lx\n"},
{DE_SIZEBLOCK, " Block size: %ld longwords\n"},
{DE_SECSPERBLK, " Sectors per Block: %ld\n"},
{DE_BLKSPERTRACK, " Blocks per track: %ld\n"},
{DE_NUMHEADS, " Number of heads: %ld\n"},
{DE_INTERLEAVE, " Interleave: %ld\n"},
{DE_LOWCYL, " Starting cylinder: %ld\n"},
{DE_UPPERCYL, " Ending cylinder: %ld\n"},
{DE_RESERVEDBLKS, "Blocks reserved at start: %ld\n"},
{DE_PREFAC, " Blocks reserved at end: %ld\n"},
{DE_BOOTBLOCKS, " Number of Boot Blocks: %ld\n"},
{DE_NUMBUFFERS, " Number of buffers: %ld\n"},
{DE_BUFMEMTYPE, " Memory Type for Buffers: 0x%lx\n"},
{DE_MAXTRANSFER, " Max bytes transferred: %ld\n"},
{DE_MASK, " Address Mask: 0x%lx\n"},
{DE_BAUD, " Baud rate: %ld\n"},
{DE_CONTROL, " Control Word: 0x%lx\n"},
{-1, ""}
};
int i;
Printf ("AmigaDOS information on device `%s':\n", dosname);
for (i = 0; table[i].offset > 0; i++)
if (table[i].offset <= de->de_TableSize)
Printf (table[i].format, ((ULONG *)de)[table[i].offset]);
Printf ("\nExec information on device `%s' (unit %ld with flags 0x%lx):\n",
execname, fss->fssm_Unit, fss->fssm_Flags);
Printf (" Device Version: %ld\n", dev->dd_Library.lib_Version);
Printf (" Device Revision: %ld\n", dev->dd_Library.lib_Revision);
Printf (" Device Driver ID: %s\n",
dev->dd_Library.lib_IdString ? dev->dd_Library.lib_IdString : "(empty)");
if (!geo)
Printf (" (Further information not available)\n");
else
{
Printf (" Sector Size: %ld\n", geo->dg_SectorSize);
Printf (" Total Sectors: %ld\n", geo->dg_TotalSectors);
Printf (" Cylinders: %ld\n", geo->dg_Cylinders);
Printf (" Number of Heads: %ld\n", geo->dg_Heads);
Printf (" Sectors per Track: %ld\n", geo->dg_TrackSectors);
Printf (" Memory Type for Buffers: 0x%lx\n", geo->dg_BufMemType);
Printf (" DeviceType: %s\n", devtype (geo->dg_DeviceType));
Printf (" Flags: 0x%lx", geo->dg_Flags);
Printf ("%s\n", (geo->dg_Flags & DGF_REMOVABLE) ? " (removable)" : "");
}
}
struct IOExtTD *opendev (char *devname, int justinfo)
{
struct MsgPort *port;
struct DosList *dlist;
struct DosEnvec de; /* drive geometry as seen by DOS */
struct FileSysStartupMsg fss;
char *execdev = NULL;
char save;
char *savepos;
savepos = strchr (devname, ':');
if (!savepos)
return NULL;
save = *savepos; /* remove ':' */
*savepos = '\0';
dlist = LockDosList (LDF_DEVICES | LDF_READ);
if (dlist)
{
struct DeviceNode *dosdev;
dosdev = (struct DeviceNode *) FindDosEntry (dlist, devname, LDF_DEVICES);
if (dosdev)
{
fss = *((struct FileSysStartupMsg *) BADDR (dosdev->dn_Startup));
de = *((struct DosEnvec *) BADDR (fss.fssm_Environ));
execdev = cstr (fss.fssm_Device);
}
UnLockDosList (LDF_DEVICES | LDF_READ);
}
*savepos = save; /* restore ':' */
if (!execdev)
return NULL;
if (port = CreateMsgPort ())
{
struct IOExtTD *diskreq;
diskreq = (struct IOExtTD *) CreateIORequest (port, sizeof (struct IOExtTD));
if (diskreq)
{
if (!OpenDevice (execdev, fss.fssm_Unit, (struct IORequest *) diskreq,
fss.fssm_Flags))
{
ULONG memtype;
struct DriveGeometry geo; /* drive geometry */
diskreq->iotd_Req.io_Length = sizeof (geo);
diskreq->iotd_Req.io_Data = (APTR) &geo;
diskreq->iotd_Req.io_Command = TD_GETGEOMETRY;
diskreq->iotd_Req.io_Offset = 0;
DoIO ((struct IORequest *) diskreq);
if (diskreq->iotd_Req.io_Error) /* TD_GETGEOMETRY not supported */
{
memtype = de.de_BufMemType;
blocksize = de.de_SizeBlock << 2; /* convert to bytes */
if (de.de_SectorPerBlock == 0)
sectorsize = blocksize;
else
sectorsize = blocksize / de.de_SectorPerBlock;
}
else
{
memtype = geo.dg_BufMemType;
blocksize = de.de_SizeBlock << 2; /* convert to bytes */
sectorsize = geo.dg_SectorSize;
}
if (justinfo)
if (diskreq->iotd_Req.io_Error)
devinfo (devname, execdev, &fss, &de, diskreq->iotd_Req.io_Device, NULL);
else
devinfo (devname, execdev, &fss, &de, diskreq->iotd_Req.io_Device, &geo);
else
{
/***
*** KLUDGE! (is this really needed?)
***/
if (strcmp (execdev, "trackdisk.device") == 0)
memtype = MEMF_CHIP;
sectorbuf = AllocMem (sectorsize, memtype);
if (sectorbuf)
{
Inhibit (devname, TRUE);
Motor (diskreq, ON);
return diskreq;
}
}
CloseDevice ((struct IORequest *) diskreq);
}
DeleteIORequest ((struct IORequest *) diskreq);
}
DeleteMsgPort (port);
}
return NULL;
}
void closedev (char *devname, struct IOExtTD *diskreq)
{
if (diskreq && devname)
{
struct IORequest *ioreq = (struct IORequest *) diskreq;
if (sectorbuf)
FreeMem (sectorbuf, sectorsize);
Motor (diskreq, OFF);
Inhibit (devname, FALSE);
CloseDevice (ioreq);
DeleteMsgPort (ioreq->io_Message.mn_ReplyPort);
DeleteIORequest (ioreq);
}
}
int deverror (long err)
{
static struct {int code; char *msg;} table[] = {
{IOERR_OPENFAIL, "could not open device/unit"},
{IOERR_NOCMD, "command not supported"},
{IOERR_BADLENGTH, "invalid lenght"},
{IOERR_BADADDRESS, "invalid address"},
{IOERR_UNITBUSY, "unit in use"},
{IOERR_SELFTEST, "hardware failed self-test"},
{TDERR_NotSpecified, "unspecified error"},
{TDERR_NoSecHdr, "couldn't find sector"},
{TDERR_BadSecPreamble, "bad sector preamble"},
{TDERR_BadSecID, "bad sector ID"},
{TDERR_BadHdrSum, "incorrect header checksum"},
{TDERR_BadSecSum, "incorrect sector checksum"},
{TDERR_TooFewSecs, "couldn't find enough sectors"},
{TDERR_BadSecHdr, "bad sector header"},
{TDERR_WriteProt, "disk is write-protected"},
{TDERR_DiskChanged, "no disk in drive"},
{TDERR_SeekError, "seek error"},
{TDERR_NoMem, "out of memory"},
{TDERR_BadUnitNum, "bad unit number"},
{TDERR_BadDriveType, "bad drive type"},
{TDERR_DriveInUse, "drive in use"},
{0, ""}
};
int i;
for (i = 0; table[i].code; i++)
if (err == table[i].code)
{
Printf ("dd: %s\n", table[i].msg);
return TRUE;
}
return FALSE;
}