home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------
- * block.cpp
- *
- * Member function definitions,
- * IOCTL for block devices
- * ------------------------------------------------- */
-
- #include "block.h"
-
- #ifndef NDEBUG
- #include <iostream.h>
-
- void IoctlBlock::IoctlError( int errval )
- {
- cerr << "*** class IoctlBlock: DOS error #"
- << errval << " encountered, subfunction #"
- << hex << _iregs.x.ax << dec << endl;
- }
- #endif // NDEBUG
-
- unsigned IoctlBlock::drive_info( int drive )
- {
- _iregs.x.bx = drive;
- int21_44h( drive_remote );
- return _oregs.x.dx;
- }
-
- IoctlBlock::IoctlBlock(int drive )
- {
- _info = drive_info( drive );
- _drive = _dos_error ? -1 : drive;
- }
-
- IoctlBlock *IoctlBlock::Init(int drive )
- {
- /* Return a pointer to a new, initialized object
- * of type IoctlBlock, NULL if specified drive
- * is invalid.
- */
-
- IoctlBlock *obj = new IoctlBlock( drive);
-
- if( obj->_drive == -1 ) { //bad drive
- delete obj;
- return (IoctlBlock *) 0;
- }
-
- return obj;
- }
-
- int IoctlBlock::block_ioctl( block_cmd minor_code,
- void *param_block )
- {
- /* Access DOS int21h/44h/0Dh for current disk
- * drive, generic ioctl for block devices. Return
- * 0 if successful, DOS error value if not.
- */
- _iregs.x.bx = _drive;
- _iregs.h.ch = 0x08; //category = disk drive
- _iregs.h.cl = (char) minor_code;
- _iregs.x.dx = FP_OFF( (void far *) param_block );
- _sregs.ds = FP_SEG( (void far *) param_block );
- int21_44h( gen_ioctl_block );
- return _dos_error ? _oregs.x.ax : 0;
- }
-
- unsigned IoctlBlock::ioctl_data( ioctl_cmd fn,
- unsigned count,
- void *buffer )
- {
- /* Send/receive I/O Control data to current block
- * device. Return #bytes successfully transfered.
- */
- _iregs.x.bx = _drive;
- _iregs.x.cx = count; //#bytes to read/write
- _iregs.x.dx = FP_OFF( (void far *) buffer );
- _sregs.ds = FP_SEG( (void far *) buffer );
- int21_44h(fn); //function number (4/5)
- return _oregs.x.ax; //#bytes xfered
- }
-
- int IoctlBlock::sendIoctl( unsigned *count,
- void *buffer )
- {
- /* Send ioctl data to current drive. Return 0 on
- * success, or DOS error value if not. Assigns
- * #bytes successfully sent to 'count'.
- */
- *count = ioctl_data( send_ioctl_block,
- *count, buffer );
- return _dos_error ? _oregs.x.ax : 0;
- }
-
- int IoctlBlock::readIoctl( unsigned *count,
- void *buffer )
- {
- *count = ioctl_data( read_ioctl_block,
- *count, buffer );
- return _dos_error ? _oregs.x.ax : 0;
- }
-
- int IoctlBlock::isRemovable(void)
- {
- /* Determine if current drive contains removable
- * storage media.
- */
- if( isRemote() || !(_info & rmvMedia) )
- return 0; //assume fixed if on network
- //or if rmvMedia bit not set
- _iregs.x.bx = _drive;
- int21_44h( drive_removable );
- return !_oregs.x.ax; //ax == 0 if removable
- }
-
- int IoctlBlock::checkAlias( void )
- {
- /* Return the active drive alias (if any) assigned
- * to the current drive, 0 if no drive aliases have
- * been assigned, or -1 on DOS error.
- */
- _iregs.x.bx = _drive;
- int21_44h(get_log_drivemap);
- return _dos_error ? -1 : (int) _oregs.h.al;
- }
-
- int IoctlBlock::nextAlias( int drive_alias )
- {
- /* Set next active (logical) drive number for the
- * current drive and return active drive number, or
- * -1 on DOS error. Assumes prior call to function
- * checkAlias(). Specified drive# is 1-based.....
- */
- _iregs.h.bl = (char) drive_alias;
- int21_44h(set_log_drivemap);
- return _dos_error ? -1 : (int) _oregs.h.al;
- }
-
- int IoctlBlock::getParams( struct DEVICEPARAMS *dpms )
- {
- return block_ioctl( get_params, (void *) dpms );
- }
-
- int IoctlBlock::setParams( struct DEVICEPARAMS *dpms )
- {
- return block_ioctl( set_params, (void *) dpms );
- }
-
- int IoctlBlock::readSectors( struct RWBLOCK *tpms )
- {
- tpms->spfun = 0;
- return block_ioctl( read_track, tpms );
- }
-
- int IoctlBlock::writeSectors( struct RWBLOCK *tpms )
- {
- tpms->spfun = 0;
- return block_ioctl( write_track, tpms );
- }
-
- int IoctlBlock::getAccessFlag(void)
- {
- /* Return current state of media access flag...
- */
- struct SPECIALFUNC sp;
- sp.spfunc = sp.acc_flag = 0;
- block_ioctl( get_access_flag, (void *) &sp);
- return (int) sp.acc_flag;
- }
-
- int IoctlBlock::setAccessFlag(int flag)
- {
- /* Set media access flag. Access flag = 0
- * if access to media is blocked (unformatted).
- * Return new flag state..........
- */
- struct SPECIALFUNC sp;
- sp.spfunc = 0;
- sp.acc_flag = (char) flag;
- block_ioctl( set_access_flag, (void *) &sp);
- return getAccessFlag();
- }
-
- int IoctlBlock::format_track( int spec,
- int head, int cyl )
- {
- /* Format (and verify) a disk track.
- */
- struct FVBLOCK fvp;
- fvp.spfunc = spec; //0=format, 1=check
- fvp.num_tracks = 0;
- fvp.disk_head = head;
- fvp.disk_cylinder = cyl;
- block_ioctl( format_and_verify, (void *) &fvp );
- return (int) fvp.spfunc;
- }
-
- int IoctlBlock::formatTrack( int head, int cyl )
- {
- format_track( 0, head, cyl) ;
- return _dos_error ? _oregs.x.ax : 0;
- }
-
- int IoctlBlock::verifyTrack( int head, int cyl )
- {
- /* Verify a disk track .... */
- struct FVBLOCK fvp;
- fvp.spfunc = fvp.num_tracks = 0;
- fvp.disk_head = head;
- fvp.disk_cylinder = cyl;
- return block_ioctl( verify_track,
- (void *) &fvp );
- }
-
- int IoctlBlock::checkFunction( block_cmd cmd )
- {
- /* Check availability of a specified IOCTL function
- * 'cmd' for the current drive ........
- */
- if( _dos.version < 0x0500 ||
- !(_info & queryIoctl) ||
- cmd == set_access_flag ||
- cmd == get_access_flag )
- return unknown; //query not supported
-
- _iregs.x.bx = _drive;
- _iregs.h.ch = 0x08; //category = disk drive
- _iregs.h.cl = (char) cmd;
- int21_44h( query_ioctl_block );
-
- if( _oregs.x.cflag == 0 )
- return is_supported;
-
- switch( _oregs.x.ax ) {
- case 0x0001: return invalid_function;
- case 0x0005: return access_denied;
- case 0x000f: return invalid_drive;
- default: return unknown;
- }
- }
-
- /* ----- End of File ------------------------------- */
-