home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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;
- }
-