/* DisDF.c V1.1 Disables DF0-DF3 */ /* Patrick F. Misteli 22.7.91 */ /* see DisDF.doc and 'usage' below */ #define ND 4 /* max floppy drives */ #define NN 100 /* max tasknodes to scan */ #define DISABLEDP -123 /* priority of disabled task */ #define BUSYPRI -122 #include #include #include #include #include #include #include #include #include #include /* LATTICE is defined in dos.h */ /* manx 3.4b doesn't have dos.h so add one with AZTEC defined in it */ #ifdef LATTICE #include #else #ifdef AZTEC struct IORequest *CreateExtIO(); struct MsgPort *CreatePort(); #include #else #define OTHER_COMPILER 1 struct IORequest *CreateExtIO(); struct MsgPort *CreatePort(); struct Task *DeviceProc(); struct Task *FindTask(); long SetTaskPri(); long Signal(); char *AllocMem(); struct Task *CreateTask(); #endif #endif extern struct ExecBase *SysBase; char extioerrmsg[] = "DisDF CreateExtIO() error"; char creatportmsg[] = "DisDF CreatePort() error"; char nofloppymsg[] = "DisDF no floppy drive found"; char notmountmsg[] = "DisDF DFi not mounted"; char missingdmsg[] = "DisDF DFi device process missing"; char missingtmsg[] = "DisDF DFi trackdisk.device task missing"; char missingfmsg[] = "DisDF DFi File Process task missing"; char memerrormsg[] = "DisDF not enough memory"; char statusokmsg[] = "DisDF DFi trackdisk oxx File System oxx"; char statusermsg[] = "DisDF DFi error"; char busytaskmsg[] = "DisDF BusyLoop-122 running"; char *usagemsg[] = { "\nDisDF V1.0 toggles floppy drives' trackdisk.device tasks off or on\n", "usage : DisDF [0] [1] [2] [3] [-d|e] [-f] [-h]", " # drive number if not all DF0: to DF3:", " -c change priorities and start busyloop task", " -d disable instead of toggle", " -e enable instead of toggle", " -f disable floppy drives' File System tasks also", " -h help message to stdout", " -s status message to stdout only, tasks not changed", " -v verbose", NULL }; char trackdisk[] = TD_NAME; /* "trackdisk.device" */ char filesystem[] = "File System"; char dfstr[] = "DF0:"; char busyname[] = "BusyLoop-122"; struct Task *me; struct Node *fnode[ ND ], *tnode[ ND ]; struct Task *busytask; int drive[ ND ], statusonly, chicken; long previouspri; main( argc, argv ) int argc; char *argv[]; { register int i; register struct Node *np; register int j, k; struct Node *anode[ NN ]; int all, en, ds, fs, verbose; unsigned failval; struct MsgPort *diskport; struct IOExtTD *ioexttd; failval = 0; all = TRUE; en = ds = fs = verbose = statusonly = chicken = FALSE; for ( i = 0; i < ND; i++ ) { drive[i] = FALSE; tnode[i] = NULL; fnode[i] = NULL; } if ( argc > 1 ) { for ( i = 1; i < argc; i++ ) { switch ( *argv[i] ) { case '-': if ( argv[ i ][ 2 ] ) usageexit(); switch( argv[ i ][ 1 ]) { case 'c': chicken = TRUE; break; case 'd': if ( en ) usageexit(); ds = TRUE; break; case 'e': if ( ds ) usageexit(); en = TRUE; break; case 'f': fs = TRUE; break; case 's': statusonly = TRUE; break; case 'v': verbose = TRUE; break; default : usageexit(); break; } break; case '0' : case '1' : case '2' : case '3' : if ( argv[i][1] != 0 ) usageexit(); drive[ *argv[i] - 48 ] = TRUE; all = FALSE; break; default: usageexit(); break; } /* switch */ } /* for i */ } /* argc > 1 */ if ( all ) drive[0] = drive[1] = drive[2] = drive[3] = TRUE; me = FindTask( 0L ); previouspri = SetTaskPri( me, -1L ); /* allow most other tasks to finish */ Forbid(); /* before grabbing the CPU until exit() */ /* find out which drives are mounted by trying to open them */ diskport = CreatePort( 0, 0 ); if( diskport == NULL ) { puts( creatportmsg ); permexit( 11 ); } ioexttd = (struct IOExtTD *)CreateExtIO( diskport, (long)sizeof(struct IOExtTD ) ); if( ioexttd == 0 ) { puts( extioerrmsg ); DeletePort( diskport ); permexit( 12 ); } for ( i = 0; i < ND; i++ ) { if ( drive[i] ) if ( !OpenDevice( trackdisk, (long)i, (struct IORequest *)ioexttd, 0L ) ) { /* get pointer to its trackdisk.device task */ tnode[i] = (struct Node *)ioexttd->iotd_Req.io_Unit->unit_MsgPort.mp_SigTask; CloseDevice( (struct IORequest *)ioexttd ); } } DeleteExtIO( (struct IORequest *)ioexttd, sizeof( struct IOExtTD ) ); DeletePort( diskport ); if ( all ) /* check that at least one drive was found */ { for ( i = 0; i < ND; i++ ) if ( tnode[i] ) break; if ( i >= ND ) { puts( nofloppymsg ); permexit( 13 ); } } else { for ( i = 0; i < ND; i++ ) /* check for drives specified in command */ if ( !tnode[i] ) if ( drive[i] ) { notmountmsg[8] = 48 + i; puts( notmountmsg ); } } for ( i = 0; i < ND; i++ ) /* find each mounted drive's File System task */ { if ( tnode[i] ) { dfstr[2] = 48 + i; fnode[i] = (struct Node *)DeviceProc( dfstr ); if ( fnode[i] ) fnode[i] = (struct Node *)( (long)fnode[i] - sizeof(struct Task) ); else { tnode[i] = NULL; missingdmsg[8] = 48 + i; puts( missingdmsg ); failval += 1 << (i + 4); } } } /* ensure that the tasks found above are in exec's task lists */ for ( i = 0; i < NN; i++ ) anode[i] = NULL; i = 0; Disable(); for ( np = (struct Node *)SysBase->TaskReady.lh_Head; i < NN, np->ln_Succ; np = np->ln_Succ ) anode[i++] = np; for ( np = (struct Node *)SysBase->TaskWait.lh_Head; i < NN, np->ln_Succ; np = np->ln_Succ ) anode[i++] = np; Enable(); for ( i = 0; i < ND; i++ ) { if ( tnode[i] ) { for ( j = 0; j < NN; j++ ) if ( tnode[i] == anode[j] ) break; if ( j >= NN ) /* if the task is not there, ignore this drive */ { tnode[i] = NULL; fnode[i] = NULL; missingtmsg[8] = 48 + i; puts( missingtmsg ); failval += 1 << (i + 8); } } if ( fnode[i] ) { for ( j = 0; j < NN; j++ ) if ( fnode[i] == anode[j] ) break; if ( j >= NN ) { tnode[i] = NULL; fnode[i] = NULL; missingfmsg[8] = 48 + i; puts( missingfmsg ); failval += 1 << (i + 12); } } } if ( statusonly ) { typestatus(); permexit( 0 ); } if ( !chicken ) { Disable(); /* remove tasks found above from exec's task lists */ for ( i = 0; i < ND; i++ ) if( tnode[i] ) { Remove( tnode[i] ); Remove( fnode[i] ); } Enable(); } for ( i = j = 0; i < ND; i++ ) /* modify priority */ { if ( tnode[i] ) { if ( en || ( ( tnode[i]->ln_Pri == DISABLEDP ) && !ds ) ) { modtask( tnode[i], 5 ); modtask( fnode[i], 10 ); } else { modtask( tnode[i], DISABLEDP ); if ( fs ) modtask( fnode[i], DISABLEDP ); else modtask( fnode[i], 10 ); } } } if ( !chicken ) { Disable(); /* put modified tasks back in exec's lists */ for ( i = 0; i < ND; i++ ) if( tnode[i] ) { if ( tnode[i]->ln_Pri == DISABLEDP ) { AddTail( &SysBase->TaskWait, tnode[i] ); AddTail( &SysBase->TaskWait, fnode[i] ); } else { AddTail( &SysBase->TaskReady, tnode[i] ); AddTail( &SysBase->TaskReady, fnode[i] ); } } Enable(); } if ( busytask = FindTask( busyname ) ) /* maybe remove busytask */ { for ( i = j = k = 0; i < ND; i++ ) if ( tnode[i] ) if ( tnode[i]->ln_Pri == DISABLEDP ) { j++; if ( ((struct Task*)tnode[i])->tc_State != TS_REMOVED ) k++; } else /* previously removed tasks in the wait list need a nudge */ { Signal( (struct Task *)tnode[i], ((struct Task *)tnode[i])->tc_SigAlloc ); Signal( (struct Task *)fnode[i], ((struct Task *)fnode[i])->tc_SigAlloc ); } if ( !j || ( !chicken && k ) ) rembusytask(); } else /* maybe add busytask */ { if ( chicken ) for ( i = 0; i < ND; i++ ) if ( tnode[i] ) if ( tnode[i]->ln_Pri == DISABLEDP ) break;; if ( i < ND ) addbusytask(); } if ( verbose ) typestatus(); permexit( failval ); } /* main */ usageexit() { register int i; for ( i = 0; usagemsg[i][0]; i++ ) puts( usagemsg[i] ); exit( 10 ); } modtask( task, pri ) /* modifies task state and priority */ struct Task *task; int pri; { task->tc_State = TS_WAIT; if ( ( ((struct Node *)task)->ln_Pri = pri ) == DISABLEDP ) if ( !chicken ) task->tc_State = TS_REMOVED; } typestatus() { register int i; for ( i = 0; i < ND; i++ ) { if ( !drive[i] ) continue; if ( tnode[i] ) { statusokmsg[8] = i + 48; if ( tnode[i]->ln_Pri == DISABLEDP ) { statusokmsg[21] = 'f'; statusokmsg[22] = 'f'; } else { statusokmsg[21] = 'n'; statusokmsg[22] = ' '; } if ( fnode[i]->ln_Pri == DISABLEDP ) { statusokmsg[37] = 'f'; statusokmsg[38] = 'f'; } else { statusokmsg[37] = 'n'; statusokmsg[38] = ' '; } puts( statusokmsg ); } else if ( !statusonly ) { statusermsg[8] = i + 48; puts( statusermsg ); } } /* for i */ if ( FindTask( busyname ) ) puts( busytaskmsg ); } /* typestatus */ permexit( exitval ) /* all exits after Forbid() come here */ unsigned exitval; { SetTaskPri( me, previouspri ); /* otherwise the CLI or WB stays at -1 */ Permit(); /* SetTaskPri() reschedules Forbidden tasks ?... */ exit( exitval ); } addbusytask() /* starts a busyloop task at priority -122 */ { char *busycode; if ( !( busycode = AllocMem( 32L, MEMF_CLEAR ) ) ) { puts( memerrormsg ); permexit( 14 ); } busycode[0] = 0x60; busycode[1] = 0xfe; /* kk: BRA kk */ CopyMemQuick( busyname, busycode + 2, 12L ); if ( !( busytask = CreateTask( busycode + 2, (long)BUSYPRI, busycode, 128L ) ) ) { FreeMem( busycode, 32L ); puts( memerrormsg ); permexit( 14 ); } busytask->tc_UserData = (APTR)busycode; } rembusytask() { char *busycode; busycode = (char *)busytask->tc_UserData; DeleteTask( busytask ); FreeMem( busycode, 32L ); } /* fin DisDF.c */