/* :ts=8 bk=0 * Disk mapper. Uses trackdisk.device to grab and read sector bitmap * to discover what's allocated, then displays a (hopefully) pretty picture * showing disk useage. * * Crufted together by Leo Schwab while desperately bored. 8606.8 * Turned into something working for the Manx compiler. 8607.23 */ #include #include #include #include #include #define REV 0L #define BLOCKSIZE TD_SECTOR #define NUMBLOCKS (NUMCYLS * NUMHEADS * NUMSECS) #define ROOTBLOCK (NUMBLOCKS / 2) #define BITMAPINDEX 79 #define NUMLONGS (NUMBLOCKS / 32) #define XX 6L #define YY 6L #define XOFF 30L #define YOFF 25L #define BRKOVER 91L /* 11 * YY + YOFF */ #define SEP 6 extern void *OpenLibrary(), *OpenDevice(), *OpenWindow(), *AllocMem(), *Lock(), *Info(), *CreatePort(), *CreateExtIO(); extern long TextLength(); struct NewWindow windef = { 0, 0, 640, 180, -1, -1, CLOSEWINDOW, WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | ACTIVATE, NULL, NULL, (UBYTE *) "Disk Allocation Map ", NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN }; struct IntuiText ok = { AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE, AUTOITEXTFONT, (UBYTE *) "OK", AUTONEXTTEXT }; struct IntuiText errmsg = { AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE, AUTOTOPEDGE, AUTOITEXTFONT, NULL, /* Gets filled in later */ AUTONEXTTEXT }; struct Window *win; struct RastPort *rp; struct InfoData *id; struct IOExtTD *diskreq; struct MsgPort *diskport; ULONG diskchangecount, lok, *diskbuffer; void *IntuitionBase, *GfxBase; main (ac, av) char *av[]; { long k, x, y; int unit, bmsect, free = NUMBLOCKS-2; short i, n, l; char buf[80]; if (!ac) { /* Run from workbench (ick!) */ /* I'll make this part better someday..... */ strcpy (buf, "df0:"); } else { /* Run from CLI (thank you) */ if (ac == 1) { printf ("Drive specifier: "); gets (buf); } else strcpy (buf, av[1]); } openstuff (); if (!(lok = Lock (buf, ACCESS_READ))) die ("Can't obtain lock for specified device."); if (!(id = AllocMem ((long) sizeof (*id), MEMF_CLEAR))) die ("Can't get InfoData memory."); if (!Info (lok, id)) die ("Call to Info() failed."); if (id -> id_DiskType == ID_NO_DISK_PRESENT) die ("No disk in drive."); unit = id -> id_UnitNumber; FreeMem (id, (long) sizeof (*id)); id = NULL; opendisk (unit); MotorOn (); GetSector ((long) ROOTBLOCK); bmsect = diskbuffer[BITMAPINDEX]; GetSector ((long) bmsect); MotorOff (); /* * At this point, we now have the bitmap in the disk buffer. * This is what the first longword in the bitmap represents: * * 333322222222221111111111 * 32109876543210987654321098765432 Sector # * -------------------------------- * 10100101001010010010010001010011 Longword * MSB LSB * * If the bit is set, the sector is free. * * Sectors 0 and 1 contain the boot block. Thus, the DOS is not * allowed to walk on them, and they are permanently allocated. * However, the bitmap does not reflect this i.e. the bitmap starts * at sector 2, which is indicated by bit 0, longword 1. This means * we have to offset everything by two. Can you say "crock?" * * Actually, I suppose this is good, since it prevents some would-be * smart person from un-allocating those sectors and messing things * up badly. * * Bitmap starts at longword 1; longword 0 appears to be some kind * of significant garbage (checksum?) * * For more info on how I found the bitmap sector, consult the DOS * Technical Reference Manual, p. 1-1 - 1-2 */ SetAPen (rp, 3L); RectFill (rp, XOFF, YOFF, XX+XOFF, YY+YY+YOFF); /* Show first two */ for (i=1; i<=NUMLONGS; i++) { k = diskbuffer[i]; for (n=0; n<32; n++) /* Bits progress from low to high order */ if (i= BRKOVER) y += SEP; RectFill (rp, x, y, x+XX-1, y+YY-1); } k >>= 1; } } /* Draw grid so we can see */ SetAPen (rp, 1L); for (x=XOFF; x<=80*XX+XOFF; x += XX) { Move (rp, x, YOFF); Draw (rp, x, YOFF+11*YY); Move (rp, x, BRKOVER+SEP); Draw (rp, x, BRKOVER+SEP+11*YY); } for (y=0; y<=11*YY; y += YY) { Move (rp, XOFF, y+YOFF); Draw (rp, XOFF+80*XX, y+YOFF); Move (rp, XOFF, y+SEP+BRKOVER); Draw (rp, XOFF+80*XX, y+SEP+BRKOVER); } /* Draw map markings */ Move (rp, XOFF+XX/2, YOFF); Draw (rp, XOFF+XX/2, YOFF-3); Move (rp, XOFF+80*XX-XX/2, YOFF); Draw (rp, XOFF+80*XX-XX/2, YOFF-3); Move (rp, XOFF, YOFF+YY/2); Draw (rp, XOFF-3, YOFF+YY/2); Move (rp, XOFF, YOFF+YY*10+YY/2); Draw (rp, XOFF-3, YOFF+YY*10+YY/2); Move (rp, XOFF-1, YOFF-3); Text (rp, "0", 1L); Move (rp, XOFF+79*XX-1, YOFF-3); Text (rp, "79", 2L); Move (rp, XOFF-12, YOFF+6); Text (rp, "0", 1L); Move (rp, XOFF-20, YOFF+11*YY); Text (rp, "10", 2L); /* Do labels */ sprintf (buf, "Bitmap on sector %d", bmsect); Move (rp, XOFF, 176L); Text (rp, buf, (long) strlen (buf)); sprintf (buf, "Sectors free: %d", free); Move (rp, 250L, 176L); Text (rp, buf, (long) strlen (buf)); sprintf (buf, "Allocated: %d", (int) NUMBLOCKS-free); Move (rp, 450L, 176L); Text (rp, buf, (long) strlen (buf)); Move (rp, 520L, 60L); Text (rp, "Surface 0", 9L); Move (rp, 520L, 132L); Text (rp, "Surface 1", 9L); /* Wait for close gadget */ Wait (1L << win -> UserPort -> mp_SigBit); closestuff (); } openstuff () { if (!(IntuitionBase = OpenLibrary ("intuition.library", REV))) { /* * If we can't open Intuition, then we can't use * AutoRequest () */ printf ("Intuition failed; you'll have to use logic.\n"); closestuff (); exit (100); } if (!(GfxBase = OpenLibrary ("graphics.library", REV))) { printf ("Art shop closed.\n"); closestuff (); exit (100); } if (!(win = OpenWindow (&windef))) { printf ("Window painted shut.\n"); closestuff (); exit (100); } rp = win -> RPort; } opendisk (unit) int unit; { long err; char *buf[80]; if (!(diskport = CreatePort (NULL, NULL))) die ("No port."); if (!(diskreq = CreateExtIO (diskport, (long) sizeof (*diskreq)))) die ("Can't make IO block."); if (err = OpenDevice (TD_NAME, (long) unit, diskreq, NULL)) { sprintf (buf, "Can't get at disk; err = %ld.", err); DeleteExtIO (diskreq, (long) sizeof (*diskreq)); diskreq = NULL; die (buf); } if (!(diskbuffer = AllocMem (BLOCKSIZE, MEMF_CLEAR | MEMF_CHIP))) die ("Can't allocate disk buffer."); diskreq -> iotd_Req.io_Command = TD_CHANGENUM; DoIO (diskreq); diskchangecount = diskreq -> iotd_Req.io_Actual; } closestuff () { if (lok) UnLock (lok); if (diskreq) { CloseDevice (diskreq); DeleteExtIO (diskreq, (long) sizeof (*diskreq)); } if (diskbuffer) FreeMem (diskbuffer, (long) BLOCKSIZE); if (id) FreeMem (id, (long) sizeof (*id)); if (diskport) DeletePort (diskport); if (win) CloseWindow (win); if (GfxBase) CloseLibrary (GfxBase); if (IntuitionBase) CloseLibrary (IntuitionBase); } die (str) UBYTE *str; { errmsg.IText = str; AutoRequest (win, &errmsg, NULL, &ok, NULL, NULL, TextLength (rp, str, (long) strlen (str)) + 40, 46L); closestuff (); exit (100); } /* * The following routines were stolen from an RKM example by Bob Peck and * hacked up a bit. */ GetSector (sector) long sector; { LONG offset = sector * BLOCKSIZE; diskreq -> iotd_Req.io_Length = BLOCKSIZE; diskreq -> iotd_Req.io_Data = (APTR) diskbuffer; /* show where to put the data when read */ diskreq -> iotd_Req.io_Command = ETD_READ; /* check that disk not changed before reading */ diskreq -> iotd_Count = diskchangecount; /* convert from cylinder, head, sector to byte-offset value to get * right one (as dos and everyone else sees it)...*/ /* driver reads one CYLINDER at a time (head does not move for * 22 sequential sector reads, or better-put, head doesnt move for * 2 sequential full track reads.) */ diskreq -> iotd_Req.io_Offset = offset; DoIO (diskreq); return (0); } MotorOn() { /* TURN ON DISK MOTOR ... old motor state is returned in io_Actual */ diskreq -> iotd_Req.io_Length = 1; /* this says motor is to be turned on */ diskreq -> iotd_Req.io_Command = TD_MOTOR; /* do something with the motor */ DoIO (diskreq); return (0); } MotorOff() { diskreq -> iotd_Req.io_Length = 0; /* says that motor is to be turned on */ diskreq -> iotd_Req.io_Command = TD_MOTOR; /* do something with the motor */ DoIO (diskreq); return (0); }