Annotation of ntddk/src/scsi/qic117/ioctl.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1993 - Colorado Memory Systems,  Inc.
        !             4: All Rights Reserved
        !             5: 
        !             6: Module Name:
        !             7: 
        !             8:     ioctl.c
        !             9: 
        !            10: Abstract:
        !            11: 
        !            12:     Tape IOCTL support for NT Backup aplication.
        !            13: 
        !            14: Revision History:
        !            15: 
        !            16: 
        !            17: 
        !            18: 
        !            19: --*/
        !            20: 
        !            21: //
        !            22: // Includes
        !            23: //
        !            24: 
        !            25: #include <ntddk.h>
        !            26: #include <ntddtape.h>   // tape device driver I/O control codes
        !            27: #include "common.h"
        !            28: #include "q117.h"
        !            29: #include "protos.h"
        !            30: #include "cms.h"
        !            31: 
        !            32: 
        !            33: NTSTATUS
        !            34: q117IoCtlGetPosition (
        !            35:     IN PDEVICE_OBJECT DeviceObject,
        !            36:     IN PIRP Irp
        !            37:     )
        !            38: /*++
        !            39: 
        !            40: Routine Description:
        !            41: 
        !            42: 
        !            43: 
        !            44: Arguments:
        !            45: 
        !            46:     DeviceObject
        !            47: 
        !            48: 
        !            49: Return Value:
        !            50: 
        !            51:     NT Status
        !            52: 
        !            53: --*/
        !            54: 
        !            55: {
        !            56:     PQ117_CONTEXT       context;
        !            57:     PTAPE_GET_POSITION  currentPosition;
        !            58:     PLARGE_INTEGER      offset;
        !            59: 
        !            60:     context = DeviceObject->DeviceExtension;
        !            61:     currentPosition = Irp->AssociatedIrp.SystemBuffer;
        !            62: 
        !            63:     Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
        !            64: 
        !            65:     //
        !            66:     // signal no partition support
        !            67:     //
        !            68:     currentPosition->Partition = 0;
        !            69: 
        !            70:     //
        !            71:     // Fill in the CurrentOperation.Position based on the mode
        !            72:     //
        !            73:     offset = &currentPosition->Offset;
        !            74: 
        !            75:     offset->HighPart = (LONG)0;
        !            76: 
        !            77: 
        !            78:     switch (context->CurrentOperation.Type) {
        !            79: 
        !            80:         case BackupInProgress:
        !            81:             offset->LowPart = context->CurrentOperation.BytesOnTape;
        !            82:             break;
        !            83: 
        !            84:         case RestoreInProgress:
        !            85:             offset->LowPart = context->CurrentOperation.BytesRead;
        !            86:             break;
        !            87: 
        !            88:         case NoOperation:
        !            89:             offset->LowPart = context->CurrentOperation.BytesRead;
        !            90:             break;
        !            91: 
        !            92:     }
        !            93:     offset->LowPart /= BLOCK_SIZE;
        !            94: 
        !            95:     CheckedDump(QIC117SHOWTD,("%d=GetPosition()",currentPosition->Offset.LowPart));
        !            96: 
        !            97:     return STATUS_SUCCESS;
        !            98: }
        !            99: 
        !           100: NTSTATUS
        !           101: q117IoCtlGetMediaParameters (
        !           102:     IN PDEVICE_OBJECT DeviceObject,
        !           103:     IN PIRP Irp
        !           104:     )
        !           105: /*++
        !           106: 
        !           107: Routine Description:
        !           108: 
        !           109: 
        !           110: 
        !           111: Arguments:
        !           112: 
        !           113:     DeviceObject
        !           114: 
        !           115: 
        !           116: Return Value:
        !           117: 
        !           118:     NT Status
        !           119: 
        !           120: --*/
        !           121: 
        !           122: {
        !           123:     PQ117_CONTEXT   context;
        !           124:     NTSTATUS        ntStatus;
        !           125: 
        !           126:     context = DeviceObject->DeviceExtension;
        !           127: 
        !           128:     //
        !           129:     // Make sure there is a tape in the drive and that the tape information
        !           130:     // has been loaded
        !           131:     //
        !           132:     if (context->CurrentOperation.Type == NoOperation) {
        !           133: 
        !           134:         ntStatus = q117ConvertStatus(DeviceObject, q117CheckNewTape(context));
        !           135: 
        !           136:     } else {
        !           137: 
        !           138:         ntStatus = STATUS_SUCCESS;
        !           139: 
        !           140:     }
        !           141: 
        !           142: 
        !           143:     if ( NT_SUCCESS( ntStatus ) ) {
        !           144:         //
        !           145:         // Copy already formed (by q117CheckNewTape) information into callers buffer
        !           146:         //
        !           147:         Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);
        !           148: 
        !           149:         *(PTAPE_GET_MEDIA_PARAMETERS)Irp->AssociatedIrp.SystemBuffer =
        !           150:             *context->CurrentTape.MediaInfo;
        !           151: 
        !           152:     }
        !           153: 
        !           154:     return ntStatus;
        !           155: }
        !           156: 
        !           157: NTSTATUS
        !           158: q117IoCtlSetMediaParameters (
        !           159:     IN PDEVICE_OBJECT DeviceObject,
        !           160:     IN PIRP Irp
        !           161:     )
        !           162: /*++
        !           163: 
        !           164: Routine Description:
        !           165: 
        !           166: 
        !           167: 
        !           168: Arguments:
        !           169: 
        !           170:     DeviceObject
        !           171: 
        !           172: 
        !           173: Return Value:
        !           174: 
        !           175:     NT Status
        !           176: 
        !           177: --*/
        !           178: 
        !           179: {
        !           180:     PQ117_CONTEXT                context;
        !           181:     PTAPE_SET_MEDIA_PARAMETERS   setMedia;
        !           182: 
        !           183:     context = DeviceObject->DeviceExtension;
        !           184: 
        !           185:     setMedia = (PTAPE_SET_MEDIA_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
        !           186: 
        !           187:     CheckedDump((QIC117SHOWTD | QIC117WARN),("SetDriveParameters not implemented yet\n"));
        !           188:     CheckedDump(QIC117SHOWTD,("BlockSize: %x",setMedia->BlockSize));
        !           189: 
        !           190:     if (setMedia->BlockSize != BLOCK_SIZE)
        !           191:         return STATUS_INVALID_PARAMETER;
        !           192:     else
        !           193:         return STATUS_SUCCESS;
        !           194: }
        !           195: 
        !           196: NTSTATUS
        !           197: q117IoCtlGetDriveParameters (
        !           198:     IN PDEVICE_OBJECT DeviceObject,
        !           199:     IN PIRP Irp
        !           200:     )
        !           201: /*++
        !           202: 
        !           203: Routine Description:
        !           204: 
        !           205: 
        !           206: 
        !           207: Arguments:
        !           208: 
        !           209:     DeviceObject
        !           210: 
        !           211: 
        !           212: Return Value:
        !           213: 
        !           214:     NT Status
        !           215: 
        !           216: --*/
        !           217: 
        !           218: {
        !           219:     PQ117_CONTEXT             context;
        !           220:     PTAPE_GET_DRIVE_PARAMETERS driveInfo;
        !           221: 
        !           222:     context = DeviceObject->DeviceExtension;
        !           223: 
        !           224:     //
        !           225:     // Copy already formed (by q117CheckNewTape) information into callers buffer
        !           226:     //
        !           227:     //
        !           228:     driveInfo = (PTAPE_GET_DRIVE_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
        !           229:     Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);
        !           230: 
        !           231:     driveInfo->ECC = TRUE;
        !           232:     driveInfo->Compression = FALSE;
        !           233:     driveInfo->DataPadding = FALSE;
        !           234:     driveInfo->ReportSetmarks = TRUE;
        !           235:     driveInfo->DefaultBlockSize = BLOCK_SIZE;
        !           236:     driveInfo->MaximumBlockSize = BLOCK_SIZE;
        !           237:     driveInfo->MinimumBlockSize = BLOCK_SIZE;
        !           238:     driveInfo->MaximumPartitionCount = 0;
        !           239:     driveInfo->FeaturesLow =
        !           240:         TAPE_DRIVE_ERASE_SHORT |
        !           241:         TAPE_DRIVE_ERASE_BOP_ONLY |
        !           242:         TAPE_DRIVE_TAPE_CAPACITY |
        !           243:         TAPE_DRIVE_TAPE_REMAINING |
        !           244:         TAPE_DRIVE_FIXED_BLOCK |
        !           245:         TAPE_DRIVE_WRITE_PROTECT |
        !           246:         TAPE_DRIVE_ECC |
        !           247:         TAPE_DRIVE_COMPRESSION |
        !           248:         TAPE_DRIVE_REPORT_SMKS |
        !           249:         TAPE_DRIVE_GET_ABSOLUTE_BLK |
        !           250:         TAPE_DRIVE_GET_LOGICAL_BLK;
        !           251:     driveInfo->FeaturesHigh =
        !           252:         TAPE_DRIVE_LOAD_UNLOAD |
        !           253:         TAPE_DRIVE_TENSION |
        !           254:         TAPE_DRIVE_LOCK_UNLOCK |
        !           255:         TAPE_DRIVE_ABSOLUTE_BLK |
        !           256:         TAPE_DRIVE_LOGICAL_BLK |
        !           257:         TAPE_DRIVE_END_OF_DATA |
        !           258:         TAPE_DRIVE_RELATIVE_BLKS |
        !           259:         TAPE_DRIVE_FILEMARKS |
        !           260:         TAPE_DRIVE_SEQUENTIAL_FMKS |
        !           261:         TAPE_DRIVE_SETMARKS |
        !           262:         TAPE_DRIVE_SEQUENTIAL_SMKS |
        !           263:         TAPE_DRIVE_REVERSE_POSITION |
        !           264:         TAPE_DRIVE_WRITE_SETMARKS |
        !           265:         TAPE_DRIVE_WRITE_FILEMARKS |
        !           266:         TAPE_DRIVE_FORMAT;
        !           267: 
        !           268:     driveInfo->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES;
        !           269: 
        !           270:     return STATUS_SUCCESS;
        !           271: }
        !           272: 
        !           273: NTSTATUS
        !           274: q117IoCtlSetDriveParameters (
        !           275:     IN PDEVICE_OBJECT DeviceObject,
        !           276:     IN PIRP Irp
        !           277:     )
        !           278: /*++
        !           279: 
        !           280: Routine Description:
        !           281: 
        !           282: 
        !           283: 
        !           284: Arguments:
        !           285: 
        !           286:     DeviceObject
        !           287: 
        !           288: 
        !           289: Return Value:
        !           290: 
        !           291:     NT Status
        !           292: 
        !           293: --*/
        !           294: 
        !           295: {
        !           296:     PQ117_CONTEXT             context;
        !           297:     PTAPE_SET_DRIVE_PARAMETERS driveInfo;
        !           298:     NTSTATUS            ntStatus;
        !           299: 
        !           300:     context = DeviceObject->DeviceExtension;
        !           301: 
        !           302:     //
        !           303:     // Copy already formed (by q117CheckNewTape) information into callers buffer
        !           304:     //
        !           305:     //
        !           306:     driveInfo = (PTAPE_SET_DRIVE_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
        !           307: 
        !           308:     CheckedDump((QIC117SHOWTD | QIC117WARN),("SetDriveParameters not implemented yet\n"));
        !           309:     CheckedDump(QIC117SHOWTD,("ECC: %x",driveInfo->ECC));
        !           310:     CheckedDump(QIC117SHOWTD,("Compression: %x",driveInfo->Compression));
        !           311:     CheckedDump(QIC117SHOWTD,("DataPadding: %x",driveInfo->DataPadding));
        !           312:     CheckedDump(QIC117SHOWTD,("ReportSetmarks: %x",driveInfo->ReportSetmarks));
        !           313:     ntStatus = STATUS_SUCCESS;
        !           314:     if (!driveInfo->ECC ||
        !           315:         driveInfo->Compression ||
        !           316:         driveInfo->DataPadding ||
        !           317:         !driveInfo->ReportSetmarks) {
        !           318: 
        !           319:         ntStatus = STATUS_INVALID_DEVICE_REQUEST;
        !           320:     }
        !           321: 
        !           322:     return ntStatus;
        !           323: }
        !           324: 
        !           325: NTSTATUS
        !           326: q117IoCtlWriteMarks (
        !           327:     IN PDEVICE_OBJECT DeviceObject,
        !           328:     IN PIRP Irp
        !           329:     )
        !           330: /*++
        !           331: 
        !           332: Routine Description:
        !           333: 
        !           334:     Handle user request to write tape mark
        !           335: 
        !           336: Arguments:
        !           337: 
        !           338:     DeviceObject
        !           339: 
        !           340: 
        !           341: Return Value:
        !           342: 
        !           343:     NT Status
        !           344: 
        !           345: --*/
        !           346: 
        !           347: {
        !           348: #ifndef NO_MARKS
        !           349: 
        !           350:     PQ117_CONTEXT       context;
        !           351:     PTAPE_WRITE_MARKS   tapeMarks = Irp->AssociatedIrp.SystemBuffer;
        !           352:     ULONG               numMarks;
        !           353:     NTSTATUS            ntStatus;
        !           354:     ULONG               type;
        !           355: 
        !           356:     context = DeviceObject->DeviceExtension;
        !           357: 
        !           358:     //
        !           359:     // Make sure we are in write mode
        !           360:     //
        !           361:     ntStatus = q117ConvertStatus(DeviceObject, q117OpenForWrite(context));
        !           362: 
        !           363:     numMarks = tapeMarks->Count;
        !           364:     type = tapeMarks->Type;
        !           365: 
        !           366:     //
        !           367:     // Don't allow long/short filemarks
        !           368:     //
        !           369:     switch(type) {
        !           370:         case TAPE_LONG_FILEMARKS:
        !           371:         case TAPE_SHORT_FILEMARKS:
        !           372:             ntStatus = STATUS_INVALID_DEVICE_REQUEST;
        !           373:     }
        !           374: 
        !           375:     //
        !           376:     // Put as many marks as the user asked for,  in the mark array
        !           377:     //
        !           378:     while (numMarks && NT_SUCCESS( ntStatus )) {
        !           379: 
        !           380:         context->MarkArray.MarkEntry[
        !           381:             context->MarkArray.TotalMarks].Type = tapeMarks->Type;
        !           382: 
        !           383:         context->MarkArray.MarkEntry[
        !           384:             context->MarkArray.TotalMarks].Offset =
        !           385:             context->CurrentOperation.BytesOnTape;
        !           386: 
        !           387:         --numMarks;
        !           388: 
        !           389:         ++context->MarkArray.TotalMarks;
        !           390:         ++context->CurrentMark;
        !           391: 
        !           392:         //
        !           393:         // Always make the (last mark) huge so we don't have to check
        !           394:         // for the end of the table in the rest of the code.
        !           395:         //
        !           396:         context->MarkArray.MarkEntry[
        !           397:             context->MarkArray.TotalMarks].Offset = 0xffffffff;
        !           398: 
        !           399:         //
        !           400:         // For each mark, write a "fake" block on the tape.  This
        !           401:         // is due to the ntBackup program assuming that a filemark
        !           402:         // takes a block
        !           403:         //
        !           404: 
        !           405:         ntStatus = q117ConvertStatus(
        !           406:             DeviceObject,
        !           407:             q117WriteTape(NULL,BLOCK_SIZE,context)
        !           408:             );
        !           409:     }
        !           410: 
        !           411:     return ntStatus;
        !           412: 
        !           413: #else
        !           414: 
        !           415:     return STATUS_INVALID_DEVICE_REQUEST;
        !           416: 
        !           417: #endif
        !           418: }
        !           419: 
        !           420: NTSTATUS
        !           421: q117IoCtlSetPosition (
        !           422:     IN PDEVICE_OBJECT DeviceObject,
        !           423:     IN PIRP Irp
        !           424:     )
        !           425: /*++
        !           426: 
        !           427: Routine Description:
        !           428: 
        !           429: 
        !           430: 
        !           431: Arguments:
        !           432: 
        !           433:     DeviceObject
        !           434: 
        !           435: 
        !           436: Return Value:
        !           437: 
        !           438:     NT Status
        !           439: 
        !           440: --*/
        !           441: 
        !           442: {
        !           443:     PQ117_CONTEXT             context;
        !           444:     PTAPE_SET_POSITION tapePosition = Irp->AssociatedIrp.SystemBuffer;
        !           445:     STATUS status;
        !           446:     NTSTATUS ntStatus;
        !           447:     IO_REQUEST ioreq;
        !           448:     ULONG offset;
        !           449: #ifndef NO_MARKS
        !           450:     int x = 0;
        !           451: #endif
        !           452: 
        !           453:     context = DeviceObject->DeviceExtension;
        !           454: 
        !           455:     status = NoErr;
        !           456:     ntStatus = STATUS_SUCCESS;
        !           457: 
        !           458:     if (context->CurrentOperation.Type != NoOperation) {
        !           459:         switch(context->CurrentOperation.Type) {
        !           460: 
        !           461:             case BackupInProgress:
        !           462:                 status = q117EndWriteOperation(context);
        !           463:                 break;
        !           464: 
        !           465:             case RestoreInProgress:
        !           466:                 if (
        !           467:                     tapePosition->Method == TAPE_REWIND
        !           468:                     ) {
        !           469:                     status = q117EndReadOperation(context);
        !           470:                 }
        !           471: 
        !           472:                 break;
        !           473:         }
        !           474:     }
        !           475: 
        !           476:     context->CurrentOperation.Position = tapePosition->Method;
        !           477:     switch(tapePosition->Method) {
        !           478: 
        !           479:         case TAPE_REWIND:
        !           480: 
        !           481:             CheckedDump(QIC117INFO,("Rewind()\n"));
        !           482:             status = q117DoCmd(&ioreq, DEject, NULL, context);
        !           483: 
        !           484: //            context->TapeStatus.Status |= TAPE_STATUS_BEGINNING_OF_MEDIA;
        !           485: //            context->TapeStatus.Status &= ~TAPE_STATUS_END_OF_MEDIA;
        !           486: 
        !           487:             context->CurrentOperation.BytesRead = 0;
        !           488: 
        !           489: #ifndef NO_MARKS
        !           490:             context->CurrentMark = 0;
        !           491: #endif
        !           492:             break;
        !           493: 
        !           494:         case TAPE_LOGICAL_BLOCK:
        !           495:         case TAPE_ABSOLUTE_BLOCK:
        !           496: 
        !           497:             CheckedDump(QIC117SHOWTD,(
        !           498:                 "%s SeekBlock(%d)\n",
        !           499:                 tapePosition->Method==TAPE_LOGICAL_BLOCK?"Logical":"Absolute",
        !           500:                 tapePosition->Offset.LowPart
        !           501:                 ));
        !           502: 
        !           503:             offset = (tapePosition->Offset.LowPart)*BLOCK_SIZE;
        !           504: 
        !           505:             ntStatus = q117SeekToOffset(offset, context, DeviceObject);
        !           506: 
        !           507:             break;
        !           508: 
        !           509:         case TAPE_SPACE_END_OF_DATA:
        !           510:             //
        !           511:             // This will be taken care of when backup starts
        !           512:             //  by using the context->CurrentOperation.Position
        !           513:             //
        !           514:             // It is assumed that this function will only be called prior
        !           515:             //  to a backup operation only.
        !           516: 
        !           517:             CheckedDump(QIC117SHOWTD,("SeekEOD()\n"));
        !           518:             context->CurrentOperation.BytesRead =
        !           519:                 context->ActiveVolume.DataSize;
        !           520: 
        !           521: #ifndef NO_MARKS
        !           522:             context->CurrentMark = context->MarkArray.TotalMarks;
        !           523: #endif
        !           524: 
        !           525: //            context->TapeStatus.Status |= TAPE_STATUS_END_OF_MEDIA;
        !           526: //            context->TapeStatus.Status &= ~TAPE_STATUS_BEGINNING_OF_MEDIA;
        !           527:             break;
        !           528: 
        !           529: 
        !           530:         case TAPE_SPACE_RELATIVE_BLOCKS:
        !           531: 
        !           532: 
        !           533:             CheckedDump(QIC117SHOWTD,("SeekRelBlock(%d)\n",tapePosition->Offset.LowPart));
        !           534:             //
        !           535:             // Convert relative offset into absolute
        !           536:             //
        !           537:             offset = (LONG)context->CurrentOperation.BytesRead +
        !           538:                     ((LONG)tapePosition->Offset.LowPart*BLOCK_SIZE);
        !           539: 
        !           540:             //
        !           541:             // Perform absolute seek.
        !           542:             //
        !           543:             ntStatus = q117SeekToOffset(offset,context, DeviceObject);
        !           544: 
        !           545:             break;
        !           546: 
        !           547: #ifndef NO_MARKS
        !           548:         case TAPE_SPACE_SETMARKS:
        !           549:             ++x;
        !           550:         case TAPE_SPACE_FILEMARKS:
        !           551:             ++x;
        !           552:         case TAPE_SPACE_SEQUENTIAL_FMKS:
        !           553:             ++x;
        !           554:         case TAPE_SPACE_SEQUENTIAL_SMKS:
        !           555:             if (1) {
        !           556:                 static char *type[4] = {"SequentialSet","SequentialFile","File","Set"};
        !           557: 
        !           558:                 CheckedDump(QIC117SHOWTD,("Seek%sMark(%d)\n",type[x],tapePosition->Offset.LowPart));
        !           559:             }
        !           560:             ntStatus = q117FindMark(tapePosition->Method,
        !           561:                          tapePosition->Offset.LowPart, context, DeviceObject);
        !           562:             break;
        !           563: #else
        !           564:         case TAPE_SPACE_SETMARKS:
        !           565:         case TAPE_SPACE_FILEMARKS:
        !           566:         case TAPE_SPACE_SEQUENTIAL_FMKS:
        !           567:         case TAPE_SPACE_SEQUENTIAL_SMKS:
        !           568: #endif
        !           569:         default:
        !           570:             CheckedDump(QIC117DBGP,("TAPE: Position: Invalid Position Code (%x)\n",
        !           571:                 tapePosition->Method));
        !           572: 
        !           573:             ntStatus = STATUS_INVALID_DEVICE_REQUEST;
        !           574:             break;
        !           575: 
        !           576:     } // end switch(tapePosition->Method)
        !           577: 
        !           578:     if (status)
        !           579:         ntStatus = q117ConvertStatus(DeviceObject, status);
        !           580: 
        !           581:     return ntStatus;
        !           582: 
        !           583: }
        !           584: 
        !           585: #ifndef NO_MARKS
        !           586: NTSTATUS
        !           587: q117FindMark(
        !           588:     ULONG Type,
        !           589:     LONG Number,
        !           590:     PQ117_CONTEXT Context,
        !           591:     IN PDEVICE_OBJECT DeviceObject
        !           592:     )
        !           593: 
        !           594: /*++
        !           595: 
        !           596: Routine Description:
        !           597: 
        !           598: 
        !           599: 
        !           600: Arguments:
        !           601: 
        !           602: 
        !           603: Return Value:
        !           604: 
        !           605:     NT Status
        !           606: 
        !           607: --*/
        !           608: 
        !           609: {
        !           610:     NTSTATUS ntStatus;
        !           611:     BOOLEAN forwardSeek;
        !           612: 
        !           613:     ntStatus = STATUS_SUCCESS;
        !           614: 
        !           615:     //
        !           616:     // Convert the SetPosition commands into WriteMark types
        !           617:     //
        !           618:     switch(Type) {
        !           619: 
        !           620:         case TAPE_SPACE_SEQUENTIAL_FMKS:
        !           621: 
        !           622:             //
        !           623:             // If sequential mark,  then always start from the first mark.
        !           624:             //
        !           625:             Context->CurrentMark = 0;
        !           626: 
        !           627:         case TAPE_SPACE_FILEMARKS:
        !           628: 
        !           629:             Type = TAPE_FILEMARKS;
        !           630:             break;
        !           631: 
        !           632:         case TAPE_SPACE_SEQUENTIAL_SMKS:
        !           633: 
        !           634:             //
        !           635:             // If sequential mark,  then always start from the first mark.
        !           636:             //
        !           637:             Context->CurrentMark = 0;
        !           638: 
        !           639:         case TAPE_SPACE_SETMARKS:
        !           640: 
        !           641:             Type = TAPE_SETMARKS;
        !           642:             break;
        !           643: 
        !           644:     }
        !           645: 
        !           646:     if (Number > 0) {
        !           647:         forwardSeek = TRUE;
        !           648:     } else {
        !           649:         forwardSeek = FALSE;
        !           650:     }
        !           651: 
        !           652: 
        !           653:     //
        !           654:     // Now seek the appropriate amount
        !           655:     //
        !           656:     while (NT_SUCCESS( ntStatus ) && Number != 0) {
        !           657: 
        !           658:         if (forwardSeek) {
        !           659: 
        !           660:             if (Context->CurrentMark >= Context->MarkArray.TotalMarks) {
        !           661: 
        !           662:                 ntStatus = STATUS_END_OF_MEDIA;
        !           663: 
        !           664:             } else {
        !           665: 
        !           666:                 if (Context->MarkArray.MarkEntry[Context->CurrentMark].Type ==
        !           667:                     Type) {
        !           668: 
        !           669:                     //
        !           670:                     // If we found one,  decrement the count
        !           671:                     //
        !           672: 
        !           673:                     --Number;
        !           674: 
        !           675: 
        !           676:                     //
        !           677:                     // Don't increment the current mark on the last one we
        !           678:                     // find.  This is because current mark points to
        !           679:                     // the mark we are going to hit next.
        !           680:                     //
        !           681: 
        !           682:                     if (Number) {
        !           683: 
        !           684:                         ++Context->CurrentMark;
        !           685:                     }
        !           686: 
        !           687:                 } else {
        !           688: 
        !           689:                     ++Context->CurrentMark;
        !           690: 
        !           691:                 }
        !           692:             }
        !           693: 
        !           694:         } else {
        !           695: 
        !           696:             if (Context->CurrentMark == 0) {
        !           697: 
        !           698:                 ntStatus = STATUS_END_OF_MEDIA;
        !           699: 
        !           700:             } else {
        !           701: 
        !           702:                 --Context->CurrentMark;
        !           703: 
        !           704:                 if (Context->MarkArray.MarkEntry[Context->CurrentMark].Type ==
        !           705:                     Type) {
        !           706: 
        !           707:                     ++Number;
        !           708: 
        !           709:                 }
        !           710: 
        !           711:             }
        !           712: 
        !           713:         }
        !           714: 
        !           715:     }
        !           716: 
        !           717:     if (NT_SUCCESS( ntStatus )) {
        !           718: 
        !           719:         if (Context->CurrentMark >= Context->MarkArray.TotalMarks) {
        !           720: 
        !           721:             ntStatus = STATUS_END_OF_MEDIA;
        !           722: 
        !           723:         } else {
        !           724: 
        !           725:             //
        !           726:             // Seek to proper location.  Note:  forward seek
        !           727:             // seeks to block after file mark (successive read will return
        !           728:             // block after filemark.
        !           729:             // A backward seek will position at the filemark.  The next read
        !           730:             // will return filemark found,  and successive reads will read
        !           731:             // data after the mark)
        !           732:             //
        !           733:             ntStatus = q117SeekToOffset(
        !           734:                 Context->MarkArray.MarkEntry[Context->CurrentMark].Offset+
        !           735:                     (forwardSeek?BLOCK_SIZE:0),
        !           736:                 Context,
        !           737:                 DeviceObject
        !           738:                 );
        !           739: 
        !           740:         }
        !           741: 
        !           742:     }
        !           743: 
        !           744:     return ntStatus;
        !           745: }
        !           746: #endif
        !           747: 
        !           748: NTSTATUS
        !           749: q117SeekToOffset(
        !           750:     ULONG Offset,
        !           751:     PQ117_CONTEXT Context,
        !           752:     IN PDEVICE_OBJECT DeviceObject
        !           753:     )
        !           754: 
        !           755: /*++
        !           756: 
        !           757: Routine Description:
        !           758: 
        !           759:     Seek to specified offset on the tape (absolute offset from 0) in bytes
        !           760: 
        !           761: Arguments:
        !           762: 
        !           763:     Offset - Bytes from begining of the volume to seek.
        !           764: 
        !           765: Return Value:
        !           766: 
        !           767:     NT Status
        !           768: 
        !           769: --*/
        !           770: 
        !           771: {
        !           772:     NTSTATUS ntStatus;
        !           773: 
        !           774: 
        !           775:     CheckedDump(QIC117SHOWTD,("Absolute seek: %x\n",Offset));
        !           776: 
        !           777:     ntStatus = STATUS_SUCCESS;
        !           778: 
        !           779:     //
        !           780:     // If not in read mode,  switch into read mode
        !           781:     //
        !           782:     if (Context->CurrentOperation.Type == NoOperation) {
        !           783: 
        !           784:         ntStatus = q117OpenForRead(0, Context, DeviceObject);
        !           785: 
        !           786:         //
        !           787:         // if there is no data on the tape
        !           788:         //
        !           789:         if (ntStatus == STATUS_NO_DATA_DETECTED) {
        !           790:             return ntStatus;
        !           791:         }
        !           792: 
        !           793:         Context->CurrentOperation.Type = RestoreInProgress;
        !           794:     }
        !           795: 
        !           796: 
        !           797:     if (Offset < Context->CurrentOperation.BytesRead) {
        !           798: 
        !           799:         //
        !           800:         // Backward seek,  so stop current operation,
        !           801:         //  rewind to begining of volume,  and drop
        !           802:         //  through to a forward seek.
        !           803:         //
        !           804: 
        !           805:         ntStatus = q117ConvertStatus(
        !           806:             DeviceObject,
        !           807:             q117EndReadOperation(Context)
        !           808:             );
        !           809: 
        !           810:         if (NT_SUCCESS(ntStatus)) {
        !           811: 
        !           812:             ntStatus = q117OpenForRead(0, Context, DeviceObject);
        !           813: 
        !           814:             //
        !           815:             // if there is no data on the tape
        !           816:             //
        !           817:             if (ntStatus == STATUS_NO_DATA_DETECTED) {
        !           818:                 return ntStatus;
        !           819:             }
        !           820: 
        !           821:             Context->CurrentOperation.Type = RestoreInProgress;
        !           822:         }
        !           823:     }
        !           824: 
        !           825: 
        !           826:     if (NT_SUCCESS(ntStatus)) {
        !           827:         //
        !           828:         // Forward seek only (if we were doing a backward seek,  the operation
        !           829:         // has been re-started this point and BytesRead == 0)
        !           830:         //
        !           831:         Offset -= Context->CurrentOperation.BytesRead;
        !           832: 
        !           833:         //
        !           834:         // Skip to the appropriate place
        !           835:         //
        !           836:         ntStatus = q117ConvertStatus(
        !           837:                         DeviceObject,
        !           838:                         q117SkipBlock(&Offset, Context)
        !           839:                         );
        !           840: 
        !           841:     }
        !           842: 
        !           843:     return ntStatus;
        !           844: }
        !           845: 
        !           846: NTSTATUS
        !           847: q117IoCtlErase (
        !           848:     IN PDEVICE_OBJECT DeviceObject,
        !           849:     IN PIRP Irp
        !           850:     )
        !           851: /*++
        !           852: 
        !           853: Routine Description:
        !           854: 
        !           855: 
        !           856: 
        !           857: Arguments:
        !           858: 
        !           859:     DeviceObject
        !           860: 
        !           861: 
        !           862: Return Value:
        !           863: 
        !           864:     NT Status
        !           865: 
        !           866: --*/
        !           867: 
        !           868: {
        !           869:     PQ117_CONTEXT             context;
        !           870:     NTSTATUS ntStatus;
        !           871:     STATUS status;
        !           872: 
        !           873:     context = DeviceObject->DeviceExtension;
        !           874: 
        !           875:     //
        !           876:     // Complete any operation in progress
        !           877:     //
        !           878:     switch(context->CurrentOperation.Type) {
        !           879: 
        !           880:         case BackupInProgress:
        !           881:             status = q117EndWriteOperation(context);
        !           882:             break;
        !           883: 
        !           884:         case RestoreInProgress:
        !           885:             status = q117EndReadOperation(context);
        !           886:             break;
        !           887:     }
        !           888: 
        !           889:     //
        !           890:     // Make sure there is a tape in the drive and that the tape information
        !           891:     // has been loaded
        !           892:     //
        !           893:     ntStatus = q117ConvertStatus(
        !           894:         DeviceObject,
        !           895:         q117CheckNewTape(context));
        !           896: 
        !           897:     if ( NT_SUCCESS( ntStatus ) ) {
        !           898:         //
        !           899:         // Don't allow an erase if write protected
        !           900:         //
        !           901:         if (context->CurrentTape.MediaInfo->WriteProtected) {
        !           902:             return STATUS_MEDIA_WRITE_PROTECTED;
        !           903:         }
        !           904: 
        !           905:         //
        !           906:         // Erase the tape
        !           907:         //
        !           908:         status = q117EraseQ(context);
        !           909: 
        !           910:         ntStatus = q117ConvertStatus(DeviceObject, status);
        !           911:     }
        !           912: 
        !           913:     return ntStatus;
        !           914: }
        !           915: 
        !           916: NTSTATUS
        !           917: q117IoCtlPrepare (
        !           918:     IN PDEVICE_OBJECT DeviceObject,
        !           919:     IN PIRP Irp
        !           920:     )
        !           921: /*++
        !           922: 
        !           923: Routine Description:
        !           924: 
        !           925: 
        !           926: 
        !           927: Arguments:
        !           928: 
        !           929:     DeviceObject
        !           930: 
        !           931: 
        !           932: Return Value:
        !           933: 
        !           934:     NT Status
        !           935: 
        !           936: --*/
        !           937: 
        !           938: {
        !           939:     PQ117_CONTEXT       context;
        !           940:     NTSTATUS            ntStatus;
        !           941:     STATUS              status;
        !           942:     PTAPE_PREPARE       tapePrepare;
        !           943:     IO_REQUEST          ioreq;
        !           944:     QIC40_VENDOR_UNIQUE vendorUnique;
        !           945:     LONG                numberBad;
        !           946: 
        !           947:     context = DeviceObject->DeviceExtension;
        !           948: 
        !           949:     status = NoErr;
        !           950: 
        !           951:     //
        !           952:     // Complete any operation in progress
        !           953:     //
        !           954:     switch(context->CurrentOperation.Type) {
        !           955: 
        !           956:         case BackupInProgress:
        !           957:             status = q117EndWriteOperation(context);
        !           958:             break;
        !           959: 
        !           960:         case RestoreInProgress:
        !           961:             status = q117EndReadOperation(context);
        !           962:             break;
        !           963:     }
        !           964: 
        !           965:     //
        !           966:     // All prepare except LOCK and UNLOCK operations rewind the media.
        !           967:     //
        !           968:     tapePrepare = Irp->AssociatedIrp.SystemBuffer;
        !           969: 
        !           970:     if ((tapePrepare->Operation != TAPE_LOCK) &&
        !           971:         (tapePrepare->Operation != TAPE_UNLOCK)) {
        !           972:         context->CurrentOperation.BytesRead = 0;
        !           973:         context->CurrentOperation.Position = 0;
        !           974: #ifndef NO_MARKS
        !           975:         context->CurrentMark = 0;
        !           976: #endif
        !           977:     }
        !           978: 
        !           979: 
        !           980:     if (status) {
        !           981:         return q117ConvertStatus(DeviceObject, status);
        !           982:     }
        !           983: 
        !           984:     ntStatus = STATUS_SUCCESS;
        !           985: 
        !           986:     switch (tapePrepare->Operation) {
        !           987: 
        !           988:         case TAPE_LOAD:
        !           989:             CheckedDump(QIC117SHOWTD,("TAPE_LOAD  ... "));
        !           990:             ntStatus = q117ConvertStatus(DeviceObject, q117CheckNewTape(context));
        !           991:             break;
        !           992: 
        !           993:         case TAPE_UNLOAD:
        !           994: 
        !           995:             //
        !           996:             // Just rewind the tape
        !           997:             //
        !           998:             CheckedDump(QIC117SHOWTD,("TAPE_UNLOAD  ... "));
        !           999:             ntStatus = q117ConvertStatus (
        !          1000:                     DeviceObject,
        !          1001:                     q117DoCmd(&ioreq, DEject, NULL, context) );
        !          1002: 
        !          1003:             break;
        !          1004: 
        !          1005:         case TAPE_TENSION:
        !          1006: 
        !          1007:             CheckedDump(QIC117SHOWTD,("TAPE_TENSION  ... "));
        !          1008:             ntStatus = q117ConvertStatus (
        !          1009:                     DeviceObject,
        !          1010:                     q117DoCmd(&ioreq, DReten, NULL, context) );
        !          1011: 
        !          1012:             break;
        !          1013: 
        !          1014:         case TAPE_UNLOCK:
        !          1015:             CheckedDump(QIC117SHOWTD,("UN"));
        !          1016:         case TAPE_LOCK:
        !          1017:             CheckedDump(QIC117SHOWTD,("LOCK TAPE ..."));
        !          1018: 
        !          1019:             //
        !          1020:             // These commands mean nothing for a QIC-40 drive.  However,  the current
        !          1021:             // operation will be flushed allowing user to remove cartridge.
        !          1022:             //
        !          1023:             break;
        !          1024: 
        !          1025:         case TAPE_FORMAT:
        !          1026:             CheckedDump(QIC117SHOWTD,("TAPE_FORMAT  ... "));
        !          1027: 
        !          1028:             ntStatus = q117ConvertStatus (
        !          1029:                         DeviceObject,
        !          1030:                         q117Format(
        !          1031:                             &numberBad,
        !          1032:                             TRUE,
        !          1033:                             &vendorUnique,
        !          1034:                             context ) );
        !          1035:             break;
        !          1036: 
        !          1037:         default:
        !          1038:             CheckedDump(QIC117SHOWTD,("INVALID  ... "));
        !          1039: 
        !          1040:             ntStatus = STATUS_INVALID_DEVICE_REQUEST;
        !          1041: 
        !          1042:     } // end switch (tapePrepare->Operation)
        !          1043: 
        !          1044:     return ntStatus;
        !          1045: }
        !          1046: 
        !          1047: NTSTATUS
        !          1048: q117IoCtlGetStatus (
        !          1049:     IN PDEVICE_OBJECT DeviceObject,
        !          1050:     IN PIRP Irp
        !          1051:     )
        !          1052: /*++
        !          1053: 
        !          1054: Routine Description:
        !          1055: 
        !          1056: 
        !          1057: 
        !          1058: Arguments:
        !          1059: 
        !          1060:     DeviceObject
        !          1061: 
        !          1062: 
        !          1063: Return Value:
        !          1064: 
        !          1065:     NT Status
        !          1066: 
        !          1067: --*/
        !          1068: 
        !          1069: {
        !          1070:     PQ117_CONTEXT             context;
        !          1071: //    PTAPE_STATUS tapeStatus;
        !          1072:     STATUS status;
        !          1073: 
        !          1074:     context = DeviceObject->DeviceExtension;
        !          1075: 
        !          1076: 
        !          1077:     //
        !          1078:     // Complete any operation in progress
        !          1079:     //
        !          1080:     switch(context->CurrentOperation.Type) {
        !          1081: 
        !          1082:         case BackupInProgress:
        !          1083:             status = NoErr;
        !          1084:             break;
        !          1085: 
        !          1086:         case RestoreInProgress:
        !          1087:             status = NoErr;
        !          1088:             break;
        !          1089: 
        !          1090:         case NoOperation:
        !          1091:             status = q117CheckNewTape(context);
        !          1092:             break;
        !          1093: 
        !          1094:         default:
        !          1095:             status = FCodeErr;
        !          1096: 
        !          1097:     }
        !          1098: 
        !          1099:     //tapeStatus = Irp->UserBuffer;
        !          1100: 
        !          1101:     //
        !          1102:     // Is this supported in the tape API ?????
        !          1103:     //
        !          1104: //    *tapeStatus = context->TapeStatus;
        !          1105: 
        !          1106:     //
        !          1107:     // Reset media changed flag.
        !          1108:     //
        !          1109: //    context->TapeStatus.Status &= ~TAPE_STATUS_MEDIA_CHANGED;
        !          1110: 
        !          1111:     return q117ConvertStatus(DeviceObject, status);
        !          1112: }
        !          1113: 
        !          1114: NTSTATUS
        !          1115: q117IoCtlReadAbs (
        !          1116:     IN PDEVICE_OBJECT DeviceObject,
        !          1117:     IN PIRP Irp
        !          1118:     )
        !          1119: /*++
        !          1120: 
        !          1121: Routine Description:
        !          1122: 
        !          1123: 
        !          1124: 
        !          1125: Arguments:
        !          1126: 
        !          1127:     DeviceObject
        !          1128: 
        !          1129: 
        !          1130: Return Value:
        !          1131: 
        !          1132:     NT Status
        !          1133: 
        !          1134: --*/
        !          1135: 
        !          1136: {
        !          1137:     PQ117_CONTEXT   context;
        !          1138:     PSEGMENT_BUFFER bufferInfo;
        !          1139:     PVOID           scrbuf;
        !          1140:     PIO_REQUEST     ioreq;
        !          1141:     PCMS_RW_ABS     readWrite;
        !          1142:     STATUS          status;
        !          1143:     ULONG           len;
        !          1144:     PIO_STACK_LOCATION  irpStack;
        !          1145: 
        !          1146:     context = DeviceObject->DeviceExtension;
        !          1147:     readWrite = Irp->AssociatedIrp.SystemBuffer;
        !          1148:     irpStack = IoGetCurrentIrpStackLocation(Irp);
        !          1149: 
        !          1150:     scrbuf = q117GetFreeBuffer(&bufferInfo,context);
        !          1151: 
        !          1152:     status=q117IssIOReq(
        !          1153:                 scrbuf,
        !          1154:                 DRead,
        !          1155:                 readWrite->Block,
        !          1156:                 bufferInfo,
        !          1157:                 context
        !          1158:                 );
        !          1159: 
        !          1160:     if (!status) {
        !          1161: 
        !          1162:         //
        !          1163:         // Wait for data to be written
        !          1164:         //
        !          1165:         ioreq=q117Dequeue(WaitForItem,context);
        !          1166: 
        !          1167:         status = ioreq->Status;
        !          1168: 
        !          1169:     }
        !          1170: 
        !          1171:     readWrite->Status = status;
        !          1172: 
        !          1173:     len = BYTES_PER_SECTOR*readWrite->Count;
        !          1174: 
        !          1175:     if (len > irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
        !          1176: 
        !          1177:         len = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
        !          1178: 
        !          1179:     }
        !          1180: 
        !          1181:     RtlMoveMemory(
        !          1182:         readWrite+1,
        !          1183:         scrbuf,
        !          1184:         len
        !          1185:         );
        !          1186: 
        !          1187:     Irp->IoStatus.Information = sizeof(CMS_RW_ABS)+len;
        !          1188: 
        !          1189:     return q117ConvertStatus(DeviceObject, status);
        !          1190: 
        !          1191: 
        !          1192: }
        !          1193: 
        !          1194: NTSTATUS
        !          1195: q117IoCtlWriteAbs (
        !          1196:     IN PDEVICE_OBJECT DeviceObject,
        !          1197:     IN PIRP Irp
        !          1198:     )
        !          1199: /*++
        !          1200: 
        !          1201: Routine Description:
        !          1202: 
        !          1203: 
        !          1204: 
        !          1205: Arguments:
        !          1206: 
        !          1207:     DeviceObject
        !          1208: 
        !          1209: 
        !          1210: Return Value:
        !          1211: 
        !          1212:     NT Status
        !          1213: 
        !          1214: --*/
        !          1215: 
        !          1216: {
        !          1217:     PQ117_CONTEXT   context;
        !          1218:     PSEGMENT_BUFFER bufferInfo;
        !          1219:     PVOID           scrbuf;
        !          1220:     PIO_REQUEST     ioreq;
        !          1221:     PCMS_RW_ABS     readWrite;
        !          1222:     STATUS          status;
        !          1223: 
        !          1224:     context = DeviceObject->DeviceExtension;
        !          1225:     readWrite = Irp->AssociatedIrp.SystemBuffer;
        !          1226: 
        !          1227:     scrbuf = q117GetFreeBuffer(&bufferInfo,context);
        !          1228: 
        !          1229:     RtlMoveMemory(
        !          1230:         scrbuf,
        !          1231:         readWrite+1,
        !          1232:         BYTES_PER_SECTOR*readWrite->Count
        !          1233:         );
        !          1234: 
        !          1235:     status = q117IssIOReq(
        !          1236:         scrbuf,
        !          1237:         DWrite,
        !          1238:         readWrite->Block,
        !          1239:         bufferInfo,
        !          1240:         context);
        !          1241: 
        !          1242:     if (!status) {
        !          1243: 
        !          1244:         //
        !          1245:         // Wait for data to be written
        !          1246:         //
        !          1247:         ioreq=q117Dequeue(WaitForItem,context);
        !          1248: 
        !          1249:         status = ioreq->Status;
        !          1250: 
        !          1251:     }
        !          1252: 
        !          1253:     readWrite->Status = status;
        !          1254: 
        !          1255:     return q117ConvertStatus(DeviceObject, status);
        !          1256: 
        !          1257: }
        !          1258: 
        !          1259: STATUS
        !          1260: q117CheckNewTape (
        !          1261:     PQ117_CONTEXT             Context
        !          1262:     )
        !          1263: /*++
        !          1264: 
        !          1265: Routine Description:
        !          1266: 
        !          1267:     This routine checks for new tape and reads header if necessary
        !          1268: 
        !          1269: Arguments:
        !          1270: 
        !          1271:     Context - Current context information
        !          1272: 
        !          1273: Return Value:
        !          1274: 
        !          1275:     NT Status
        !          1276: 
        !          1277: --*/
        !          1278: 
        !          1279: {
        !          1280:     STATUS              stat;
        !          1281:     IO_REQUEST          ioreq;
        !          1282:     PTAPE_HEADER        header;
        !          1283:     VOLUME_TABLE_ENTRY  tempVolume;
        !          1284:     UCHAR               tapeType;
        !          1285:     BOOLEAN             found;
        !          1286:     BOOLEAN             notNt;
        !          1287:     USHORT              volumesRead;
        !          1288:     DRIVE_CAPACITY      driveCapacity;
        !          1289:     SEGMENT             curseg;
        !          1290: 
        !          1291: 
        !          1292:     //
        !          1293:     // Check to see if there is a tape in the drive
        !          1294:     //
        !          1295:     stat = q117DoCmd(&ioreq, DGetCart, &tapeType, Context);
        !          1296: 
        !          1297:     //
        !          1298:     // If we found a tape and need to read the header and volume tables,
        !          1299:     //   do it now.
        !          1300:     //
        !          1301:     if (stat == NewCart) {
        !          1302: //        Context->TapeStatus.Status |= TAPE_STATUS_MEDIA_CHANGED;
        !          1303:     }
        !          1304: 
        !          1305:     if (stat == NewCart ||
        !          1306:             (stat == NoErr && Context->CurrentTape.State == NeedInfoLoaded) ) {
        !          1307: 
        !          1308:         CheckedDump(QIC117SHOWTD,("New Cart Detected\n"));
        !          1309: 
        !          1310:         //
        !          1311:         // Check to see if there is a tape in the drive
        !          1312:         //
        !          1313: 
        !          1314:         stat = q117DoCmd(&ioreq, DClearNewCart, NULL, Context);
        !          1315: 
        !          1316:         if (stat) {
        !          1317:             return stat;
        !          1318:         }
        !          1319: 
        !          1320:         //
        !          1321:         // Saw new cart,  so set need loaded flag
        !          1322:         //
        !          1323:         Context->CurrentTape.State = NeedInfoLoaded;
        !          1324: 
        !          1325:         // clear no media flag and end of media flag
        !          1326: //        Context->TapeStatus.Status &=
        !          1327: //            ~(TAPE_STATUS_NO_MEDIA|TAPE_STATUS_END_OF_MEDIA);
        !          1328: 
        !          1329:         // Set bom and device ready.
        !          1330: //        Context->TapeStatus.Status |=
        !          1331: //            TAPE_STATUS_DEVICE_READY|TAPE_STATUS_BEGINNING_OF_MEDIA;
        !          1332: 
        !          1333:         //
        !          1334:         // Check to see if tape is write protected
        !          1335:         //
        !          1336:         if (stat = q117DoCmd(&ioreq, DSndWPro, NULL, Context)) {
        !          1337: 
        !          1338:             if (stat != WProt) {
        !          1339:                 return stat;
        !          1340:             }
        !          1341: 
        !          1342:         }
        !          1343: 
        !          1344:         Context->CurrentTape.MediaInfo->WriteProtected = (stat == WProt);
        !          1345:         if (stat == WProt) {
        !          1346: //            Context->TapeStatus.Status |= TAPE_STATUS_WRITE_PROTECTED;
        !          1347:         }
        !          1348: 
        !          1349:         //
        !          1350:         // Check to see if drive is formatted
        !          1351:         //
        !          1352:         stat = q117DoCmd(&ioreq, DGetCap, &driveCapacity, Context);
        !          1353: 
        !          1354:         if (stat) {
        !          1355:             return stat;
        !          1356:         }
        !          1357: 
        !          1358:         //
        !          1359:         // If tape not referenced.
        !          1360:         //
        !          1361:         if (driveCapacity.referenced == FALSE) {
        !          1362:             return BadFmt;
        !          1363:         }
        !          1364: 
        !          1365:         //
        !          1366:         // Check to see if tape is correct format
        !          1367:         //
        !          1368:         stat = q117DoCmd(&ioreq, DChkFmt, NULL, Context);
        !          1369: 
        !          1370:         if (stat) {
        !          1371:             if (stat == WrongFmt) {
        !          1372:                 Context->CurrentTape.MediaInfo->WriteProtected =
        !          1373:                     TRUE;
        !          1374:                 stat = NoErr;
        !          1375:             } else {
        !          1376:                 return stat;
        !          1377:             }
        !          1378:         }
        !          1379: 
        !          1380:         //
        !          1381:         // Now read the tape header (and bad sector map)
        !          1382:         //
        !          1383:         if (stat = q117LoadTape(&header,Context)) {
        !          1384:             return stat;
        !          1385:         }
        !          1386:         CheckedDump(QIC117SHOWTD,("LoadTape successful\n"));
        !          1387: 
        !          1388:         //
        !          1389:         // If this capacity not supported by this drive,
        !          1390:         // (i.e..  Pegasus cart in a QIC-40 drive)
        !          1391:         // return invalid format
        !          1392:         //
        !          1393:         if (header->FormatCode != driveCapacity.TapeFormatCode) {
        !          1394:             return BadFmt;
        !          1395:         }
        !          1396: 
        !          1397:         //
        !          1398:         // Copy over bad sector map, etc.
        !          1399:         //
        !          1400:         RtlMoveMemory(
        !          1401:             Context->CurrentTape.TapeHeader,
        !          1402:             header,
        !          1403:             sizeof(*Context->CurrentTape.TapeHeader) );
        !          1404: 
        !          1405:         //
        !          1406:         // Now scan volume list and get last volume on tape as well as the
        !          1407:         // NT volume (if one exists
        !          1408:         //
        !          1409: 
        !          1410:         if (stat = q117SelectTD(Context))
        !          1411:             return stat;
        !          1412: 
        !          1413:         volumesRead = 0;
        !          1414: 
        !          1415:         found = FALSE;
        !          1416: 
        !          1417:         do {
        !          1418:             /* get a volume directory from the tape (if error then)*/
        !          1419:             stat = q117ReadVolumeEntry(&tempVolume,Context);
        !          1420: 
        !          1421:             if (stat && (stat != EndOfVol))
        !          1422:                 return stat;
        !          1423: 
        !          1424:             if (!stat) {
        !          1425:                 volumesRead++;
        !          1426: 
        !          1427:                 //
        !          1428:                 // For now,  let the system find ANY volume type and select
        !          1429:                 // it.  This will allow NT Backup software to read the
        !          1430:                 // volume and detect that it is a non-nt format.
        !          1431:                 // To do this,  the if statement is removed,  allowing
        !          1432:                 // the first volume found,  be the one that we select.
        !          1433:                 //
        !          1434:                 if (!(tempVolume.VendorSpecific &&
        !          1435:                     tempVolume.Vendor.cms_QIC40.OpSysType == OP_WINDOWS_NT)) {
        !          1436: 
        !          1437:                     Context->CurrentOperation.BytesOnTape =
        !          1438:                         Context->CurrentOperation.BytesRead = 0;
        !          1439: 
        !          1440:                     notNt = TRUE;
        !          1441: 
        !          1442: #ifndef NO_MARKS
        !          1443:                     Context->MarkArray.TotalMarks = 0;
        !          1444:                     Context->CurrentMark = Context->MarkArray.TotalMarks;
        !          1445:                     Context->MarkArray.MarkEntry[Context->CurrentMark].Offset =
        !          1446:                         0xffffffff;
        !          1447: #endif
        !          1448: 
        !          1449:                     /* force the data size to be the entire backup */
        !          1450:                     tempVolume.DataSize = 0;
        !          1451:                     curseg = tempVolume.StartSegment;
        !          1452:                     while (curseg <= tempVolume.EndingSegment) {
        !          1453: 
        !          1454:                         tempVolume.DataSize +=
        !          1455:                             q117GoodDataBytes(
        !          1456:                                 curseg,
        !          1457:                                 Context);
        !          1458:                         ++curseg;
        !          1459: 
        !          1460: 
        !          1461:                     }
        !          1462: 
        !          1463:                 } else {
        !          1464: 
        !          1465:                     notNt = FALSE;
        !          1466: 
        !          1467:                 }
        !          1468:                 found = TRUE;
        !          1469:                 Context->ActiveVolume = tempVolume;
        !          1470:             }
        !          1471: 
        !          1472:         } while (!stat && volumesRead < Context->CurrentTape.MaximumVolumes);
        !          1473: 
        !          1474:         if (stat = q117EndRest(Context))
        !          1475:             return(stat);
        !          1476: 
        !          1477:         //
        !          1478:         // If we did not find a volume,  then signal others that
        !          1479:         //  the ActiveVolume information is invalid.
        !          1480:         //
        !          1481:         if (!found)
        !          1482:             Context->ActiveVolumeNumber = 0;
        !          1483: 
        !          1484:         //
        !          1485:         // Zero out bytes saved (incase user trys to read)
        !          1486:         // Also set CurrentOperation.BytesRead to zero (start of tape)
        !          1487:         //
        !          1488:         Context->CurrentOperation.BytesOnTape =
        !          1489:             Context->CurrentOperation.BytesRead = 0;
        !          1490: 
        !          1491:         //
        !          1492:         // Flag that we have done everything
        !          1493:         //
        !          1494:         Context->CurrentTape.State = TapeInfoLoaded;
        !          1495: 
        !          1496: #ifndef NO_MARKS
        !          1497: 
        !          1498:         //
        !          1499:         // Read the mark list from the active volume
        !          1500:         //
        !          1501:         if (found && !notNt) {
        !          1502: 
        !          1503:             stat = q117GetMarks(Context);
        !          1504: 
        !          1505:         }
        !          1506: 
        !          1507: #endif
        !          1508: 
        !          1509:         //
        !          1510:         // If no more pressing error,  return NewCart
        !          1511:         // so application can be aware of the new insertion.
        !          1512:         //
        !          1513:         if (stat == NoErr) {
        !          1514:             stat = NewCart;
        !          1515:         }
        !          1516: 
        !          1517:     } else {
        !          1518: 
        !          1519:         if (stat == NoTape) {
        !          1520: //            Context->TapeStatus.Status |= TAPE_STATUS_NO_MEDIA;
        !          1521:             Context->ActiveVolumeNumber = 0;
        !          1522:             Context->CurrentOperation.BytesOnTape =
        !          1523:                 Context->CurrentOperation.BytesRead = 0;
        !          1524: 
        !          1525: #ifndef NO_MARKS
        !          1526:             Context->MarkArray.TotalMarks = 0;
        !          1527:             Context->CurrentMark = Context->MarkArray.TotalMarks;
        !          1528:             Context->MarkArray.MarkEntry[Context->CurrentMark].Offset =
        !          1529:                 0xffffffff;
        !          1530: #endif
        !          1531: 
        !          1532:         }
        !          1533: 
        !          1534:     }
        !          1535: 
        !          1536:     return stat;
        !          1537: }
        !          1538: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.