Annotation of ntddk/src/scsi/qic117/q117i_nt.c, revision 1.1.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:     q117i_nt.c
                      9: 
                     10: Abstract:
                     11: 
                     12:     NT device driver entry point,  NT interface routines,
                     13:     and thread for low-level irp functions.
                     14: 
                     15: Revision History:
                     16: 
                     17: 
                     18: 
                     19: 
                     20: --*/
                     21: 
                     22: #include "ntddk.h"                        // various NT definitions
                     23: #include "ntdddisk.h"                    // disk device driver I/O control codes
                     24: #include "common.h"
                     25: #include "drvtask.h"                    // this driver's data declarations
                     26: #include "mt1defs.h"                    // this driver's data declarations
                     27: #include "mt1strc.h"                    // this driver's data declarations
                     28: #include "q117data.h"               // this driver's data declarations
                     29: #include "hilevel.h"
                     30: 
                     31: //
                     32: // This is the actual definition of FloppyDebugLevel.
                     33: // Note that it is only defined if this is a "debug"
                     34: // build.
                     35: //
                     36: #if DBG
                     37: // extern ULONG QIC117DebugLevel = QIC117DBGP | QIC117WARN | QIC117INFO |
                     38: //                                QIC117SHOWTD | QIC117SHOWQD |
                     39: //                                QIC117SHOWPOLL | QIC117STOP |
                     40: //                                QIC117MAKEBAD | QIC117SHOWBAD |
                     41: //                                QIC117DRVSTAT;
                     42: 
                     43: extern ULONG QIC117DebugLevel = 0x00000000;
                     44: //extern ULONG QIC117DebugLevel =  QIC117SHOWTD | QIC117DBGP | QIC117WARN | QIC117INFO;
                     45: 
                     46: #endif
                     47: 
                     48: #ifdef ALLOC_PRAGMA
                     49: #pragma alloc_text(init,DriverEntry)
                     50: #endif
                     51: 
                     52: 
                     53: NTSTATUS
                     54: DriverEntry(
                     55:    IN OUT PDRIVER_OBJECT DriverObject,
                     56:    IN PUNICODE_STRING RegistryPath
                     57:    )
                     58: 
                     59: /*++
                     60: 
                     61: Routine Description:
                     62: 
                     63:    This routine is the driver's entry point, called by the I/O system
                     64:    to load the driver. This routine can be called any number of times,
                     65:    as long as the IO system and the configuration manager conspire to
                     66:    give it an unmanaged controller to support at each call.    It could
                     67:    also be called a single time and given all of the controllers at
                     68:    once.
                     69: 
                     70:    It initializes the passed-in driver object, calls the configuration
                     71:    manager to learn about the devices that it is to support, and for
                     72:    each controller to be supported it calls a routine to initialize the
                     73:    controller (and all drives attached to it).
                     74: 
                     75: Arguments:
                     76: 
                     77:    DriverObject - a pointer to the object that represents this device
                     78:    driver.
                     79: 
                     80: Return Value:
                     81: 
                     82:    If we successfully initialize at least one drive, STATUS_SUCCESS is
                     83:    returned.
                     84: 
                     85:    If we don't (because the configuration manager returns an error, or
                     86:    the configuration manager says that there are no controllers or
                     87:    drives to support, or no controllers or drives can be successfully
                     88:    initialized), then the last error encountered is propogated.
                     89: 
                     90: --*/
                     91: 
                     92: {
                     93:    PCONFIG_DATA configData;            // pointer to config mgr's returned data
                     94:    NTSTATUS ntStatus;
                     95:    UCHAR controllerNumber;
                     96:    BOOLEAN partlySuccessful = FALSE;   // TRUE if any controller init'd properly
                     97: 
                     98:    UNREFERENCED_PARAMETER(RegistryPath);
                     99:    CheckedDump(QIC117INFO,( "DriverEntry...\n" ));
                    100: 
                    101:    //
                    102:    // Ask configuration manager for information on the hardware that
                    103:    // we're supposed to support.
                    104:    //
                    105: 
                    106: #if DBG
                    107: 
                    108: //    DbgBreakPoint();
                    109: 
                    110: #endif
                    111: 
                    112:    ntStatus = Q117iGetConfigurationInformation( &configData );
                    113: 
                    114:    //
                    115:    // If Q117iGetConfigurationInformation() failed, just exit and propogate
                    116:    // the error.   If it said that there are no controllers to support,
                    117:    // return an error.
                    118:    // Otherwise, try to init the controllers.  If at least one succeeds,
                    119:    // return STATUS_SUCCESS, otherwise return the last error.
                    120:    //
                    121: 
                    122:    configData->FloppyTapeCount = 0;
                    123: 
                    124:    if ( NT_SUCCESS( ntStatus ) ) {
                    125: 
                    126:       //
                    127:       // Call Q117iInitializeController() for each controller (and its
                    128:       // attached drives) that we're supposed to support.
                    129:       //
                    130:       // Return success if we successfully initialize at least one
                    131:       // device; propogate error otherwise.   Set an error first in
                    132:       // case there aren't any controllers.
                    133:       //
                    134: 
                    135:       ntStatus = STATUS_NO_SUCH_DEVICE;
                    136: 
                    137:       for ( controllerNumber = 0;
                    138:                controllerNumber < configData->NumberOfControllers;
                    139:                controllerNumber++ ) {
                    140: 
                    141:             ntStatus = Q117iInitializeController(
                    142:                configData,
                    143:                controllerNumber,
                    144:                DriverObject,
                    145:                RegistryPath );
                    146: 
                    147:             if ( NT_SUCCESS( ntStatus ) ) {
                    148: 
                    149:                partlySuccessful = TRUE;
                    150:             }
                    151:       }
                    152: 
                    153:       if ( partlySuccessful ) {
                    154: 
                    155:             ntStatus = STATUS_SUCCESS;
                    156: 
                    157:             //
                    158:             // Initialize the driver object with this driver's entry points.
                    159:             //
                    160: 
                    161:             DriverObject->MajorFunction[IRP_MJ_READ] =
                    162:                q117Read;
                    163:             DriverObject->MajorFunction[IRP_MJ_WRITE] =
                    164:                q117Write;
                    165:             DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
                    166:                q117DeviceControl;
                    167:             DriverObject->MajorFunction[IRP_MJ_CREATE] =
                    168:                q117Create;
                    169:             DriverObject->MajorFunction[IRP_MJ_CLOSE] =
                    170:                q117Close;
                    171:             //DriverObject->MajorFunction[IRP_MJ_CLEANUP] =
                    172:             //    q117Cleanup;
                    173:             DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
                    174:                Q117iTapeDispatchInternalDeviceControl;
                    175:       }
                    176:    }
                    177: 
                    178:    //
                    179:    // NOTE: FUTURE delete configdata, if config mgr design calls for it
                    180:    //
                    181: 
                    182: #if DBG
                    183: 
                    184:    if ( !NT_SUCCESS( ntStatus ) ) {
                    185: 
                    186:       CheckedDump((QIC117INFO | QIC117DBGP),( "q117i: exiting with error %lx\n", ntStatus ));
                    187:    }
                    188: 
                    189: #endif
                    190: 
                    191:    if (configData) {
                    192: 
                    193:       ExFreePool(configData);
                    194: 
                    195:    }
                    196: 
                    197:    return ntStatus;
                    198: }
                    199: 
                    200: NTSTATUS
                    201: Q117iTapeDispatchInternalDeviceControl(
                    202:    IN PDEVICE_OBJECT DeviceObject,
                    203:    IN OUT PIRP Irp
                    204:    )
                    205: 
                    206: /*++
                    207: 
                    208: Routine Description:
                    209: 
                    210:    This routine is called by the I/O system to perform a device I/O
                    211:    control function.
                    212: 
                    213: Arguments:
                    214: 
                    215:    DeviceObject - a pointer to the object that represents the device
                    216:    that I/O is to be done on.
                    217: 
                    218:    Irp - a pointer to the I/O Request Packet for this request.
                    219: 
                    220: Return Value:
                    221: 
                    222:    STATUS_SUCCESS or STATUS_PENDING if recognized I/O control code,
                    223:    STATUS_INVALID_DEVICE_REQUEST otherwise.
                    224: 
                    225: --*/
                    226: 
                    227: {
                    228:    PIO_STACK_LOCATION irpSp;
                    229:    NTSTATUS ntStatus;
                    230:    PTAPE_EXTENSION tapeExtension;
                    231: 
                    232:    tapeExtension = DeviceObject->DeviceExtension;
                    233: 
                    234:    irpSp = IoGetCurrentIrpStackLocation( Irp );
                    235: 
                    236: 
                    237:    switch( irpSp->Parameters.DeviceIoControl.IoControlCode) {
                    238: 
                    239:    case IOCTL_QIC117_CLEAR_QUEUE:
                    240: 
                    241:    (VOID) KeResetEvent( &tapeExtension->QControllerData->ClearQueueEvent );
                    242: 
                    243:    tapeExtension->QControllerData->ClearQueue = TRUE;
                    244:    tapeExtension->QControllerData->AbortRequested = TRUE;
                    245: 
                    246:             IoMarkIrpPending( Irp );
                    247: 
                    248:       (VOID) ExInterlockedInsertTailList(
                    249:             &tapeExtension->QControllerData->ListEntry,
                    250:             &Irp->Tail.Overlay.ListEntry,
                    251:             &tapeExtension->QControllerData->ListSpinLock );
                    252: 
                    253:       (VOID) KeReleaseSemaphore(
                    254:             &tapeExtension->QControllerData->RequestSemaphore,
                    255:             (KPRIORITY) 0,
                    256:             1,
                    257:             FALSE );
                    258: 
                    259: 
                    260:    (VOID) KeWaitForSingleObject(
                    261:             (PVOID) &tapeExtension->QControllerData->ClearQueueEvent,
                    262:             Suspended,
                    263:             KernelMode,
                    264:             FALSE,
                    265:             (PLARGE_INTEGER) NULL );
                    266: 
                    267:    tapeExtension->QControllerData->ClearQueue = FALSE;
                    268:       ntStatus = STATUS_SUCCESS;
                    269: 
                    270:       break;
                    271: 
                    272:    case IOCTL_QIC117_DRIVE_REQUEST:
                    273: 
                    274:             IoMarkIrpPending( Irp );
                    275: 
                    276:       (VOID) ExInterlockedInsertTailList(
                    277:             &tapeExtension->QControllerData->ListEntry,
                    278:             &Irp->Tail.Overlay.ListEntry,
                    279:             &tapeExtension->QControllerData->ListSpinLock );
                    280: 
                    281:       (VOID) KeReleaseSemaphore(
                    282:             &tapeExtension->QControllerData->RequestSemaphore,
                    283:             (KPRIORITY) 0,
                    284:             1,
                    285:             FALSE );
                    286: 
                    287:       ntStatus = STATUS_PENDING;
                    288:       break;
                    289: 
                    290:    default:
                    291:       CheckedDump(QIC117DBGP,("q117i: invalid device request %x\n",
                    292:       irpSp->Parameters.DeviceIoControl.IoControlCode ));
                    293: 
                    294:       ntStatus = STATUS_INVALID_DEVICE_REQUEST;
                    295: 
                    296:    }
                    297: 
                    298:    return ntStatus;
                    299: }
                    300: 
                    301: BOOLEAN
                    302: Q117iTapeInterruptService(
                    303:    IN PKINTERRUPT Interrupt,
                    304:    IN OUT PVOID Context
                    305:    )
                    306: 
                    307: /*++
                    308: 
                    309: Routine Description:
                    310: 
                    311:    This routine is called at DIRQL by the system when the controller
                    312:    interrupts.
                    313: 
                    314: Arguments:
                    315: 
                    316:    Interrupt - a pointer to the interrupt object.
                    317: 
                    318:    Context - a pointer to our controller data area for the controller
                    319:    that interrupted.   (This was set up by the call to
                    320:    IoConnectInterrupt).
                    321: 
                    322: Return Value:
                    323: 
                    324:    Normally returns TRUE, but will return FALSE if this interrupt was
                    325:    not expected.
                    326: 
                    327: --*/
                    328: 
                    329: {
                    330:     PTAPE_CONTROLLER_DATA controllerData;
                    331:     PDEVICE_OBJECT currentDeviceObject;
                    332:     SHORT i;
                    333:     UCHAR statusByte;
                    334:     BOOLEAN controllerStateError = FALSE;
                    335: 
                    336:     UNREFERENCED_PARAMETER( Interrupt );
                    337: 
                    338:     KeStallExecutionProcessor(10);
                    339: 
                    340:     controllerData = (PTAPE_CONTROLLER_DATA) Context;
                    341: 
                    342:     //
                    343:     // CurrentDeviceObject is set to the device object that is
                    344:     // expecting an interrupt.
                    345:     //
                    346: 
                    347:     currentDeviceObject = controllerData->CurrentDeviceObject;
                    348: 
                    349:     if (currentDeviceObject == NULL &&
                    350:         !controllerData->CurrentInterrupt) {
                    351: 
                    352:         return FALSE;
                    353: 
                    354:     } else {
                    355: 
                    356:                        controllerData->CurrentDeviceObject = NULL;
                    357: 
                    358:                        if ( controllerData->CommandHasResultPhase ) {
                    359: 
                    360:                                 //
                    361:                                 // Result phase of previous command.    (Note that we can't trust
                    362:                                 // the CMD_BUSY bit in the status register to tell us whether
                    363:                                 // there's result bytes or not; it's sometimes wrong).
                    364:                                 // By reading the first result byte, we reset the interrupt.
                    365:                                 // The other result bytes will be read by a thread.
                    366:                                 // Note that we want to do this even if the interrupt is
                    367:                                 // unexpected, to make sure the interrupt is dismissed.
                    368:                                 //
                    369: 
                    370:                                 if ( ( READ_CONTROLLER( &controllerData->FDC_Addr->MSDSR.msr )
                    371:                                          & (MSR_RQM | MSR_DIO) ) == (MSR_RQM | MSR_DIO) ) {
                    372: 
                    373:                                          controllerData->FifoByte =
                    374:                                                        READ_CONTROLLER( &controllerData->FDC_Addr->dr );
                    375: 
                    376:                                 } else {
                    377: 
                    378:                                          //
                    379:                                          // Should never get here.   If we do, DON'T wake up the thread;
                    380:                                          // let it time out and reset the controller, or let another
                    381:                                          // interrupt handle this.
                    382:                                          //
                    383: 
                    384:                                          CheckedDump(QIC117DBGP,( "q117i: controller not ready to be read in ISR\n" ));
                    385: 
                    386:                                          controllerStateError = TRUE;
                    387: 
                    388:                                 }
                    389: 
                    390:                        } else {
                    391: 
                    392:                                 //
                    393:                                 // Previous command doesn't have a result phase. To read how it
                    394:                                 // completed, issue a sense interrupt command.  Don't read
                    395:                                 // the result bytes from the sense interrupt; that is the
                    396:                                 // responsibility of the calling thread.
                    397:                                 // Note that we want to do this even if the interrupt is
                    398:                                 // unexpected, to make sure the interrupt is dismissed.
                    399:                                 //
                    400: 
                    401:                                 i = FDC_MSR_RETRIES;
                    402: 
                    403:                                 do {
                    404: 
                    405:                                          if ((READ_CONTROLLER(&controllerData->FDC_Addr->MSDSR.msr) & (MSR_RQM | MSR_DIO)) == MSR_RQM) {
                    406: 
                    407:                                                                 break;
                    408: 
                    409:                                          }
                    410: 
                    411:                                          KeStallExecutionProcessor( 12 );
                    412: 
                    413:                                 } while (--i > 0);
                    414: 
                    415:                                 if (i != 0) {
                    416: 
                    417:                                          WRITE_CONTROLLER(
                    418:                                          &controllerData->FDC_Addr->dr,
                    419:                                          FDC_SNS_INT );
                    420: 
                    421:                                          KeStallExecutionProcessor( 12 );
                    422: 
                    423:                                          //
                    424:                                          // Wait for the controller to ACK the SenseInterrupt command, by
                    425:                                          // showing busy.    On very fast machines we can end up running
                    426:                                          // driver's system-thread before the controller has had time to
                    427:                                          // set the busy bit.
                    428:                                          //
                    429: 
                    430:                                          for (i = FDC_MSR_RETRIES; i; i--) {
                    431: 
                    432:                                                        if (READ_CONTROLLER(&controllerData->FDC_Addr->MSDSR.msr) & MSR_CB)
                    433:                                                                          break;
                    434: 
                    435:                                                        KeStallExecutionProcessor( 12 );
                    436: 
                    437:                                          }
                    438: 
                    439:                                          // Need to optimize the previous section
                    440: 
                    441:                                          if ( currentDeviceObject == NULL ) {
                    442: 
                    443:                                                        //
                    444:                                                        // This is an unexpected interrupt, so nobody's going to
                    445:                                                        // read the result bytes.   Read them now.
                    446:                                                        //
                    447: 
                    448:                                                        READ_CONTROLLER( &controllerData->FDC_Addr->dr );
                    449:                                                        READ_CONTROLLER( &controllerData->FDC_Addr->dr );
                    450: 
                    451:                                          }
                    452: 
                    453:                                 } else {
                    454: 
                    455:                                          //
                    456:                                          // Shouldn't get here.  If we do, DON'T wake up the thread;
                    457:                                          // let it time out and reset the controller, or let another
                    458:                                          // interrupt take care of it.
                    459:                                          //
                    460: 
                    461:                                          CheckedDump(QIC117DBGP,( "q117i: no result, but can't write SenseIntr\n" ));
                    462: 
                    463:                                          controllerStateError = TRUE;
                    464:                                 }
                    465: 
                    466:                        }
                    467: 
                    468:                        //
                    469:                        // We've written to the controller, and we're about to leave.   On
                    470:                        // machines with levelsensitive interrupts, we'll get another interrupt
                    471:                        // if we RETURN before the port is flushed. To make sure that doesn't
                    472:                        // happen, we'll do a read here.
                    473:                        //
                    474: 
                    475:                        statusByte = READ_CONTROLLER( &controllerData->FDC_Addr->MSDSR.msr );
                    476: 
                    477:                        //
                    478:                        // Let the interrupt settle.
                    479:                        //
                    480: 
                    481:                        KeStallExecutionProcessor(10);
                    482: 
                    483:                        if ( currentDeviceObject == NULL ) {
                    484: 
                    485:                                 //
                    486:                                 // We didn't expect this interrupt. We've dismissed it just
                    487:                                 // in case, but now return FALSE withOUT waking up the thread.
                    488:                                 //
                    489: 
                    490:                                 CheckedDump(QIC117DBGP,( "q117i: unexpected interrupt\n" ));
                    491: 
                    492:                                 return FALSE;
                    493: 
                    494:                        }
                    495: 
                    496:                        if ( !controllerStateError ) {
                    497: 
                    498:                                 //
                    499:                                 // Request a DPC for execution later to get the remainder of the
                    500:                                 // floppy state.
                    501:                                 //
                    502: 
                    503:                                 IoRequestDpc(
                    504:                                 currentDeviceObject,
                    505:                                 currentDeviceObject->CurrentIrp,
                    506:                                 (PVOID) NULL );
                    507: 
                    508:                        }
                    509: 
                    510:                        return TRUE;
                    511: 
                    512:     }
                    513: 
                    514: }
                    515: 
                    516: VOID
                    517: Q117iTapeDeferredProcedure(
                    518:    IN PKDPC Dpc,
                    519:    IN PVOID DeferredContext,
                    520:    IN PVOID SystemArgument1,
                    521:    IN PVOID SystemArgument2
                    522:    )
                    523: 
                    524: /*++
                    525: 
                    526: Routine Description:
                    527: 
                    528:    This routine is called at DISPATCH_LEVEL by the system at the
                    529:    request of Q117iTapeInterruptService(). It simply sets the interrupt
                    530:    event, which wakes up the floppy thread.
                    531: 
                    532: Arguments:
                    533: 
                    534:    Dpc - a pointer to the DPC object used to invoke this routine.
                    535: 
                    536:    DeferredContext - a pointer to the device object associated with this
                    537:    DPC.
                    538: 
                    539:    SystemArgument1 - unused.
                    540: 
                    541:    SystemArgument2 - unused.
                    542: 
                    543: Return Value:
                    544: 
                    545:    None.
                    546: 
                    547: --*/
                    548: 
                    549: {
                    550:     PDEVICE_OBJECT deviceObject;
                    551:     PTAPE_EXTENSION tapeExtension;
                    552:     union format_header hdrData;      // sector id data
                    553:     FDC_STATUS fStat;                 // FDC status response
                    554:     SHORT statLength;                 // length of FDC status response
                    555:     ULONG  *hdrPtr;                   // pointer to sector id data for format
                    556:     PHYSICAL_ADDRESS val;
                    557:     struct seek_cmd seek;
                    558:     struct fdc_result result;
                    559:     SHORT i;
                    560: 
                    561:    UNREFERENCED_PARAMETER( Dpc );
                    562:    UNREFERENCED_PARAMETER( SystemArgument1 );
                    563:    UNREFERENCED_PARAMETER( SystemArgument2 );
                    564: 
                    565:    deviceObject = (PDEVICE_OBJECT) DeferredContext;
                    566:    tapeExtension = deviceObject->DeviceExtension;
                    567: 
                    568: 
                    569:     if (!tapeExtension->QControllerData->StartFormatMode) {
                    570: 
                    571:         (VOID) KeSetEvent(
                    572:                                &tapeExtension->QControllerData->InterruptEvent,
                    573:                                (KPRIORITY) 0,
                    574:                                FALSE );
                    575: 
                    576:          } else {
                    577: 
                    578:                        //
                    579:                        // Format all of the segments on the tape track.  Whenever a boundary
                    580:                        // condition is reached (e.g. sectors > sectors per floppy track)
                    581:                        // update the sector id information as necessary.
                    582:                        //
                    583: 
                    584:                        if (tapeExtension->FmtOp.Segments == (SHORT)tapeExtension->TapeParms.SegTtrack) {
                    585: 
                    586:                                 IoFlushAdapterBuffers(
                    587:                                          tapeExtension->QControllerData->AdapterObject,
                    588:                                          tapeExtension->FmtOp.MdlAddress,
                    589:                                          tapeExtension->QControllerData->MapRegisterBase,
                    590:                                          (PVOID)( (ULONG) MmGetMdlVirtualAddress( tapeExtension->FmtOp.MdlAddress )
                    591:                                                        + tapeExtension->RdWrOp.BytesTransferredSoFar ),
                    592:                                          tapeExtension->RdWrOp.TotalBytesOfTransfer,
                    593:                                          DMA_READ );
                    594: 
                    595:                                 if ((tapeExtension->FmtOp.retval = Q117iReadFDC(
                    596:                                                                          tapeExtension,
                    597:                                                                          (CHAR *)&fStat,
                    598:                                                                          &statLength)) == NoErr) {
                    599: 
                    600:                                          if (fStat.ST0 & ST0_IC) {
                    601: 
                    602:                                                        tapeExtension->FmtOp.retval = TimeOut;
                    603: 
                    604:                      (VOID) KeSetEvent(
                    605:                                             &tapeExtension->QControllerData->InterruptEvent,
                    606:                                             (KPRIORITY) 0,
                    607:                                             FALSE );
                    608: 
                    609:                                          }
                    610: 
                    611:                                 }
                    612: 
                    613:                                 tapeExtension->QControllerData->StartFormatMode = FALSE;
                    614: 
                    615:                                 if (tapeExtension->QControllerData->FDC_Pcn < 128) {
                    616: 
                    617:                                          seek.NCN = tapeExtension->QControllerData->FDC_Pcn + Report_Status;
                    618: 
                    619:                                 } else {
                    620: 
                    621:                                          seek.NCN = tapeExtension->QControllerData->FDC_Pcn - Report_Status;
                    622: 
                    623:                                 }
                    624: 
                    625:                                 seek.cmd = 0x0f;
                    626:                                 seek.drive = (UCHAR)tapeExtension->DriveParms.DriveSelect;
                    627:                                 tapeExtension->FmtOp.NCN = seek.NCN;
                    628: 
                    629:                       tapeExtension->QControllerData->CurrentDeviceObject =
                    630:                                     tapeExtension->QDeviceObject;
                    631: 
                    632:                                 if ((tapeExtension->FmtOp.retval = Q117iProgramFDC(
                    633:                                                                          tapeExtension,
                    634:                                                                          (CHAR *)&seek,
                    635:                                                                          sizeof(seek),
                    636:                                                                          FALSE)) == NoErr) {
                    637: 
                    638:                                          tapeExtension->QControllerData->EndFormatMode = TRUE;
                    639: 
                    640:                                 } else {
                    641: 
                    642:                                          //
                    643:                                          // Request a DPC for execution later to get the remainder of the
                    644:                                          // floppy state.
                    645:                                          //
                    646: 
                    647:                  (VOID) KeSetEvent(
                    648:                                         &tapeExtension->QControllerData->InterruptEvent,
                    649:                                         (KPRIORITY) 0,
                    650:                                         FALSE );
                    651: 
                    652:                                 }
                    653: 
                    654:                        } else if (tapeExtension->FmtOp.Segments == 0) {
                    655: 
                    656:                                  if ((tapeExtension->FmtOp.retval = Q117iReadFDC(
                    657:                                                                                                                         tapeExtension,
                    658:                                                                                                                         (CHAR *)&result,
                    659:                                                                                                                         (SHORT *)&statLength)) == NoErr) {
                    660: 
                    661:                                                if ( !(result.ST0 & ST0_IC)) {
                    662: 
                    663:                                                         //
                    664:                                                         // If we timed out, then we did the sense interrupt status
                    665:                                                         // without clearing the interrupt from the interrupt controller.
                    666:                                                         // Since the FDC did not indicate an error, we assume that we
                    667:                                                         // missed the interrupt and send the EOI. Only needed for an
                    668:                                                         // 82072.
                    669:                                                         //
                    670: 
                    671:                                                         if (tapeExtension->QControllerData->InterfaceType != MicroChannel) {
                    672: 
                    673:                                                                  if (result.ST0 !=
                    674:                                                                                (UCHAR)(tapeExtension->DriveParms.DriveSelect | ST0_SE)) {
                    675: 
                    676:                                                                                tapeExtension->FmtOp.retval = NECFlt;
                    677: 
                    678:                                                                  }
                    679:                                                         }
                    680: 
                    681:                                                         if (tapeExtension->FmtOp.NCN != result.PCN) {
                    682: 
                    683:                                                                  tapeExtension->FmtOp.retval = CmdFlt;
                    684: 
                    685:                                                         }
                    686: 
                    687:                                                         tapeExtension->QControllerData->FDC_Pcn = result.PCN;
                    688: 
                    689:                                                } else {
                    690: 
                    691:                                                         tapeExtension->FmtOp.retval = NECFlt;
                    692: 
                    693:                                                }
                    694: 
                    695:                                  }
                    696: 
                    697:                                 if (tapeExtension->FmtOp.retval == NoErr) {
                    698: 
                    699:                                          hdrPtr = tapeExtension->FmtOp.HdrPtr;
                    700:                                          hdrData.hdr_struct.C = tapeExtension->FmtOp.Cylinder;
                    701:                                          hdrData.hdr_struct.H = tapeExtension->FmtOp.Head;
                    702:                                          hdrData.hdr_struct.N = FMT_BPS;
                    703: 
                    704:                                          for (i = 0; i < tapeExtension->TapeParms.FsectSeg; i++) {
                    705: 
                    706:                                                        hdrData.hdr_struct.R = tapeExtension->FmtOp.Sector++;
                    707:                                                        *hdrPtr = hdrData.hdr_all;
                    708:                                                        ++hdrPtr;
                    709: 
                    710:                                          }
                    711: 
                    712:                                          //
                    713:                                          // Start the format by programming the DMA, starting the tape, and
                    714:                                          // starting the floppy controller.
                    715:                                          //
                    716:                                          // Map the transfer through the DMA hardware.
                    717:                                          //
                    718: 
                    719:                                          tapeExtension->RdWrOp.BytesTransferredSoFar = 0l;
                    720:                                          tapeExtension->RdWrOp.TotalBytesOfTransfer =
                    721:                                                        tapeExtension->TapeParms.FsectSeg * sizeof(ULONG);
                    722: 
                    723:                                          KeFlushIoBuffers( tapeExtension->FmtOp.MdlAddress, !DMA_READ, TRUE );
                    724: 
                    725:                                          val = IoMapTransfer(
                    726:                                                        tapeExtension->QControllerData->AdapterObject,
                    727:                                                        tapeExtension->FmtOp.MdlAddress,
                    728:                                                        tapeExtension->QControllerData->MapRegisterBase,
                    729:                                                        (PVOID)( (ULONG) MmGetMdlVirtualAddress(tapeExtension->FmtOp.MdlAddress)
                    730:                                                                 + tapeExtension->RdWrOp.BytesTransferredSoFar ),
                    731:                                                        &tapeExtension->RdWrOp.TotalBytesOfTransfer,
                    732:                                                        DMA_READ );
                    733: 
                    734:                                  tapeExtension->QControllerData->CurrentDeviceObject =
                    735:                                              tapeExtension->QDeviceObject;
                    736: 
                    737:                                          if ((tapeExtension->FmtOp.retval = Q117iProgramFDC(
                    738:                                                                                                                                 tapeExtension,
                    739:                                                                                                                                 (CHAR *)&tapeExtension->QControllerData->FmtCmd,
                    740:                                                                                                                                 sizeof(FORMAT_CMD),
                    741:                                                                                                                                 TRUE)) != NoErr) {
                    742: 
                    743:                                                        IoFlushAdapterBuffers(
                    744:                                                                 tapeExtension->QControllerData->AdapterObject,
                    745:                                                                 tapeExtension->FmtOp.MdlAddress,
                    746:                                                                 tapeExtension->QControllerData->MapRegisterBase,
                    747:                                                                 (PVOID)( (ULONG) MmGetMdlVirtualAddress( tapeExtension->FmtOp.MdlAddress )
                    748:                                                                          + tapeExtension->RdWrOp.BytesTransferredSoFar ),
                    749:                                                                 tapeExtension->RdWrOp.TotalBytesOfTransfer,
                    750:                                                                 DMA_READ );
                    751: 
                    752:                      (VOID) KeSetEvent(
                    753:                                             &tapeExtension->QControllerData->InterruptEvent,
                    754:                                             (KPRIORITY) 0,
                    755:                                             FALSE );
                    756: 
                    757:                                          }
                    758: 
                    759:                                          tapeExtension->FmtOp.Segments++;
                    760:                                                  
                    761:                                 } else {
                    762: 
                    763:                  (VOID) KeSetEvent(
                    764:                                         &tapeExtension->QControllerData->InterruptEvent,
                    765:                                         (KPRIORITY) 0,
                    766:                                         FALSE );
                    767: 
                    768:                                 }
                    769: 
                    770: 
                    771:                        } else {
                    772: 
                    773:                                 IoFlushAdapterBuffers(
                    774:                                          tapeExtension->QControllerData->AdapterObject,
                    775:                                          tapeExtension->FmtOp.MdlAddress,
                    776:                                          tapeExtension->QControllerData->MapRegisterBase,
                    777:                                          (PVOID)( (ULONG) MmGetMdlVirtualAddress( tapeExtension->FmtOp.MdlAddress )
                    778:                                                        + tapeExtension->RdWrOp.BytesTransferredSoFar ),
                    779:                                          tapeExtension->RdWrOp.TotalBytesOfTransfer,
                    780:                                          DMA_READ );
                    781: 
                    782:                                 if ((tapeExtension->FmtOp.retval = Q117iReadFDC(
                    783:                                                                          tapeExtension,
                    784:                                                                          (CHAR *)&fStat,
                    785:                                                                          &statLength)) == NoErr) {
                    786: 
                    787:                                          if (fStat.ST0 & ST0_IC) {
                    788: 
                    789:                                                        tapeExtension->FmtOp.retval = TimeOut;
                    790: 
                    791:                                          }
                    792:                                 }
                    793: 
                    794:                                 if (tapeExtension->FmtOp.retval != NoErr) {
                    795: 
                    796:                  (VOID) KeSetEvent(
                    797:                                         &tapeExtension->QControllerData->InterruptEvent,
                    798:                                         (KPRIORITY) 0,
                    799:                                         FALSE );
                    800: 
                    801:                                 }
                    802: 
                    803:                                 if (tapeExtension->FmtOp.Sector > tapeExtension->TapeParms.FsectFtrack) {
                    804: 
                    805:                                          tapeExtension->FmtOp.Sector = 1;
                    806:                                          tapeExtension->FmtOp.Cylinder++;
                    807: 
                    808:                                          if (tapeExtension->FmtOp.Cylinder ==
                    809:                                                        (UCHAR)tapeExtension->TapeParms.FtrackFside) {
                    810: 
                    811:                                                        tapeExtension->FmtOp.Cylinder = 0;
                    812:                                                        tapeExtension->FmtOp.Head++;
                    813: 
                    814:                                          }
                    815:                                 }
                    816: 
                    817:                                 //
                    818:                                 // Set up the sector id information for this segment.
                    819:                                 //
                    820: 
                    821: 
                    822:                                 hdrPtr = tapeExtension->FmtOp.HdrPtr;
                    823:                                 hdrData.hdr_struct.C = tapeExtension->FmtOp.Cylinder;
                    824:                                 hdrData.hdr_struct.H = tapeExtension->FmtOp.Head;
                    825:                                 hdrData.hdr_struct.N = FMT_BPS;
                    826: 
                    827:                                 for (i = 0; i < tapeExtension->TapeParms.FsectSeg; i++) {
                    828: 
                    829:                                          hdrData.hdr_struct.R = tapeExtension->FmtOp.Sector++;
                    830:                                          *hdrPtr = hdrData.hdr_all;
                    831:                                          ++hdrPtr;
                    832: 
                    833:                                 }
                    834: 
                    835:                                 //
                    836:                                 // Start the format by programming the DMA, starting the tape, and
                    837:                                 // starting the floppy controller.
                    838:                                 //
                    839:                                 // Map the transfer through the DMA hardware.
                    840:                                 //
                    841: 
                    842:                                 tapeExtension->RdWrOp.BytesTransferredSoFar = 0l;
                    843:                                 tapeExtension->RdWrOp.TotalBytesOfTransfer =
                    844:                                          tapeExtension->TapeParms.FsectSeg * sizeof(ULONG);
                    845: 
                    846:                                 KeFlushIoBuffers( tapeExtension->FmtOp.MdlAddress, !DMA_READ, TRUE );
                    847: 
                    848:                                 val = IoMapTransfer(
                    849:                                          tapeExtension->QControllerData->AdapterObject,
                    850:                                          tapeExtension->FmtOp.MdlAddress,
                    851:                                          tapeExtension->QControllerData->MapRegisterBase,
                    852:                                          (PVOID)( (ULONG) MmGetMdlVirtualAddress(tapeExtension->FmtOp.MdlAddress)
                    853:                                                        + tapeExtension->RdWrOp.BytesTransferredSoFar ),
                    854:                                          &tapeExtension->RdWrOp.TotalBytesOfTransfer,
                    855:                                          DMA_READ );
                    856: 
                    857:                                 tapeExtension->QControllerData->CurrentDeviceObject =
                    858:                                     tapeExtension->QDeviceObject;
                    859: 
                    860:                                 if ((tapeExtension->FmtOp.retval = Q117iProgramFDC(
                    861:                                                                 tapeExtension,
                    862:                                                                 (CHAR *)&tapeExtension->QControllerData->FmtCmd,
                    863:                                                                 sizeof(FORMAT_CMD),
                    864:                                                                 TRUE)) != NoErr) {
                    865: 
                    866:                                          IoFlushAdapterBuffers(
                    867:                                                        tapeExtension->QControllerData->AdapterObject,
                    868:                                                        tapeExtension->FmtOp.MdlAddress,
                    869:                                                        tapeExtension->QControllerData->MapRegisterBase,
                    870:                                                        (PVOID)( (ULONG) MmGetMdlVirtualAddress( tapeExtension->FmtOp.MdlAddress )
                    871:                                                                 + tapeExtension->RdWrOp.BytesTransferredSoFar ),
                    872:                                                        tapeExtension->RdWrOp.TotalBytesOfTransfer,
                    873:                                                        DMA_READ );
                    874: 
                    875:                  (VOID) KeSetEvent(
                    876:                                         &tapeExtension->QControllerData->InterruptEvent,
                    877:                                         (KPRIORITY) 0,
                    878:                                         FALSE );
                    879: 
                    880:                                 }      
                    881: 
                    882:                                 tapeExtension->FmtOp.Segments++;
                    883:                                         
                    884:                        }
                    885: 
                    886:          }
                    887: 
                    888: }
                    889: 
                    890: VOID
                    891: Q117iTapeUnloadDriver(
                    892:    IN PDRIVER_OBJECT DriverObject
                    893:    )
                    894: 
                    895: /*++
                    896: 
                    897: Routine Description:
                    898: 
                    899:    This routine is called by the system to remove the driver from memory.
                    900: 
                    901:    When this routine is called, there is no I/O being done to this device.
                    902:    The driver object is passed in, and from this the driver can find and
                    903:    delete all of its device objects, extensions, etc.
                    904: 
                    905: Arguments:
                    906: 
                    907:    DriverObject - a pointer to the object associated with this device
                    908:    driver.
                    909: 
                    910: Return Value:
                    911: 
                    912:    None.
                    913: 
                    914: --*/
                    915: 
                    916: {
                    917:    UNREFERENCED_PARAMETER( DriverObject );
                    918: 
                    919: //  signal Q117iTapeThread() to unload itself
                    920: //  disable interrupts from controller(s?)
                    921: //  delete everything that's been allocated
                    922: }
                    923: 
                    924: VOID
                    925: Q117iTapeThread(
                    926:    PTAPE_CONTROLLER_DATA ControllerData
                    927:    )
                    928: 
                    929: /*++
                    930: 
                    931: Routine Description:
                    932: 
                    933:    This is the code executed by the system thread created when the
                    934:    floppy driver initializes.  This thread loops forever (or until a
                    935:    flag is set telling the thread to kill itself) processing packets
                    936:    put into the queue by the dispatch routines.
                    937: 
                    938:    For each packet, this thread calls appropriate routines to process
                    939:    the request, and then calls FlFinishOperation() to complete the
                    940:    packet.
                    941: 
                    942: Arguments:
                    943: 
                    944:    ControllerData - a pointer to our data area for the controller being
                    945:    supported (there is one thread per controller).
                    946: 
                    947: Return Value:
                    948: 
                    949:    None.
                    950: 
                    951: --*/
                    952: 
                    953: {
                    954:    PIRP irp;
                    955:    PIO_STACK_LOCATION irpSp;
                    956:    PLIST_ENTRY request;
                    957:    NTSTATUS ntStatus = 0;
                    958: 
                    959:    //
                    960:    // Set thread priority to lowest realtime level.
                    961:    //
                    962: 
                    963:    KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
                    964: 
                    965:    do {
                    966: 
                    967:       //
                    968:       // Wait for a request from the dispatch routines.
                    969:       // KeWaitForSingleObject won't return error here - this thread
                    970:       // isn't alertable and won't take APCs, and we're not passing in
                    971:       // a timeout.
                    972:       //
                    973: 
                    974:       (VOID) KeWaitForSingleObject(
                    975:             (PVOID) &ControllerData->RequestSemaphore,
                    976:             UserRequest,
                    977:             KernelMode,
                    978:             FALSE,
                    979:             (PLARGE_INTEGER) NULL );
                    980: 
                    981:       if ( ControllerData->UnloadingDriver ) {
                    982: 
                    983:             CheckedDump(QIC117INFO,( "q117i: Thread asked to kill itself\n" ));
                    984: 
                    985:             PsTerminateSystemThread( STATUS_SUCCESS );
                    986:       }
                    987: 
                    988:       while ( !IsListEmpty( &( ControllerData->ListEntry ) ) ) {
                    989: 
                    990:             //
                    991:             // Get the request from the queue. We know there is one,
                    992:             // because of the check above.
                    993:             //
                    994: 
                    995:                request = ExInterlockedRemoveHeadList(
                    996:                &ControllerData->ListEntry,
                    997:                &ControllerData->ListSpinLock );
                    998: 
                    999: 
                   1000:             ControllerData->QueueEmpty =
                   1001:                   IsListEmpty( &( ControllerData->ListEntry ) );
                   1002: 
                   1003:             irp = CONTAINING_RECORD( request, IRP, Tail.Overlay.ListEntry );
                   1004: 
                   1005:             irpSp = IoGetCurrentIrpStackLocation( irp );
                   1006: 
                   1007:             if ( ControllerData->ClearQueue ||
                   1008:                irpSp->Parameters.DeviceIoControl.IoControlCode ==
                   1009:                IOCTL_QIC117_CLEAR_QUEUE) {
                   1010: 
                   1011:                if (irpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_QIC117_CLEAR_QUEUE) {
                   1012: 
                   1013:                   CheckedDump(QIC117INFO,("Q117i: processing IOCTL_QIC117_CLEAR_QUEUE : TRUE\n"));
                   1014: 
                   1015:                   irp->IoStatus.Status = Q117iClearIO( irp );
                   1016: 
                   1017:                   // NOTE: This is temporary until we ca find how to
                   1018:                   // correctly free the Mdl using the io subsytem.
                   1019:                   if (irp->MdlAddress != NULL) {
                   1020:                         IoFreeMdl(irp->MdlAddress);
                   1021:                         irp->MdlAddress = NULL;
                   1022:                   }
                   1023: 
                   1024:                   IoCompleteRequest( irp, IO_DISK_INCREMENT );
                   1025: 
                   1026:                   (VOID) KeSetEvent(
                   1027:                         &ControllerData->ClearQueueEvent,
                   1028:                         (KPRIORITY) 0,
                   1029:                         FALSE );
                   1030: 
                   1031:                } else {
                   1032: 
                   1033:                   CheckedDump(QIC117INFO,("Q117i: processing IOCTL_QIC117_DRIVE_REQUEST : TRUE\n"));
                   1034: 
                   1035:                   irp->IoStatus.Status = STATUS_CANCELLED;
                   1036: 
                   1037:                   // NOTE: This is temporary until we ca find how to
                   1038:                   // correctly free the Mdl using the io subsytem.
                   1039:                   if (irp->MdlAddress != NULL) {
                   1040:                         IoFreeMdl(irp->MdlAddress);
                   1041:                         irp->MdlAddress = NULL;
                   1042:                   }
                   1043: 
                   1044:                   IoCompleteRequest( irp, IO_DISK_INCREMENT );
                   1045: 
                   1046:                }
                   1047: 
                   1048:             } else {
                   1049: 
                   1050:                irp->IoStatus.Status = Q117iProcessItem( irp );
                   1051: 
                   1052:                // NOTE: This is temporary until we ca find how to
                   1053:                // correctly free the Mdl using the io subsytem.
                   1054:                if (irp->MdlAddress != NULL) {
                   1055:                   IoFreeMdl(irp->MdlAddress);
                   1056:                   irp->MdlAddress = NULL;
                   1057:                }
                   1058: 
                   1059:                IoCompleteRequest( irp, IO_DISK_INCREMENT );
                   1060: 
                   1061:             }
                   1062: 
                   1063:       }                                   //while there's packets to process
                   1064: 
                   1065:    } while ( TRUE );
                   1066: }
                   1067: 
                   1068: IO_ALLOCATION_ACTION
                   1069: Q117iTapeAllocateAdapterChannel(
                   1070:    IN PDEVICE_OBJECT DeviceObject,
                   1071:    IN PIRP Irp,
                   1072:    IN PVOID MapRegisterBase,
                   1073:    IN PVOID Context
                   1074:    )
                   1075: 
                   1076: /*++
                   1077: 
                   1078: Routine Description:
                   1079: 
                   1080:    This DPC is called whenever the floppy thread is trying to allocate
                   1081:    the adapter channel (like before doing a read or write).    It saves
                   1082:    the MapRegisterBase in the controller data area, and sets the
                   1083:    AllocateAdapterChannelEvent to awaken the thread.
                   1084: 
                   1085: Arguments:
                   1086: 
                   1087:    DeviceObject - unused.
                   1088: 
                   1089:    Irp - unused.
                   1090: 
                   1091:    MapRegisterBase - the base of the map registers that can be used
                   1092:    for this transfer.
                   1093: 
                   1094:    Context - a pointer to our controller data area.
                   1095: 
                   1096: Return Value:
                   1097: 
                   1098:    Returns Allocation Action 'KeepObject' which means that the adapter
                   1099:    object will be held for now (to be released explicitly later).
                   1100: 
                   1101: --*/
                   1102: {
                   1103:    PTAPE_CONTROLLER_DATA controllerData = (PTAPE_CONTROLLER_DATA) Context;
                   1104: 
                   1105:    UNREFERENCED_PARAMETER( DeviceObject );
                   1106:    UNREFERENCED_PARAMETER( Irp );
                   1107: 
                   1108:    controllerData->MapRegisterBase = MapRegisterBase;
                   1109: 
                   1110:    (VOID) KeSetEvent(
                   1111:       &controllerData->AllocateAdapterChannelEvent,
                   1112:       0L,
                   1113:       FALSE );
                   1114: 
                   1115:    return KeepObject;
                   1116: }
                   1117: 
                   1118: NTSTATUS
                   1119: Q117iConfigCallBack(
                   1120:    IN PVOID Context,
                   1121:    IN PUNICODE_STRING PathName,
                   1122:    IN INTERFACE_TYPE BusType,
                   1123:    IN ULONG BusNumber,
                   1124:    IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
                   1125:    IN CONFIGURATION_TYPE ControllerType,
                   1126:    IN ULONG ControllerNumber,
                   1127:    IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
                   1128:    IN CONFIGURATION_TYPE PeripheralType,
                   1129:    IN ULONG PeripheralNumber,
                   1130:    IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
                   1131:    )
                   1132: 
                   1133: /*++
                   1134: 
                   1135: Routine Description:
                   1136: 
                   1137:    This routine is used to acquire all of the configuration
                   1138:    information for each floppy disk controller and the
                   1139:    peripheral driver attached to that controller.
                   1140: 
                   1141: Arguments:
                   1142: 
                   1143:    Context - Pointer to the confuration information we are building
                   1144:                up.
                   1145: 
                   1146:    PathName - unicode registry path.   Not Used.
                   1147: 
                   1148:    BusType - Internal, Isa, ...
                   1149: 
                   1150:    BusNumber - Which bus if we are on a multibus system.
                   1151: 
                   1152:    BusInformation - Configuration information about the bus. Not Used.
                   1153: 
                   1154:    ControllerType - Should always be DiskController.
                   1155: 
                   1156:    ControllerNumber - Which controller if there is more than one
                   1157:                         controller in the system.
                   1158: 
                   1159:    ControllerInformation - Array of pointers to the three pieces of
                   1160:                            registry information.
                   1161: 
                   1162:    PeripheralType - Should always be FloppyDiskPeripheral.
                   1163: 
                   1164:    PeripheralNumber - Which floppy if this controller is maintaining
                   1165:                         more than one.
                   1166: 
                   1167:    PeripheralInformation - Array of pointers to the three pieces of
                   1168:                            registry information.
                   1169: 
                   1170: Return Value:
                   1171: 
                   1172:    STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
                   1173:    if it couldn't map the base csr or acquire the adapter object, or
                   1174:    all of the resource information couldn't be acquired.
                   1175: 
                   1176: --*/
                   1177: 
                   1178: {
                   1179: 
                   1180:    //
                   1181:    // So we don't have to typecast the context.
                   1182:    //
                   1183:    PCONFIG_DATA config = Context;
                   1184: 
                   1185:    //
                   1186:    // Simple iteration variable.
                   1187:    //
                   1188:    ULONG i;
                   1189: 
                   1190:    //
                   1191:    // This boolean will be used to denote whether we've seen this
                   1192:    // controller before.
                   1193:    //
                   1194:    BOOLEAN newController;
                   1195: 
                   1196:    //
                   1197:    // This will be used to denote whether we even have room
                   1198:    // for a new controller.
                   1199:    //
                   1200:    BOOLEAN outOfRoom;
                   1201: 
                   1202:    //
                   1203:    // Iteration variable that will end up indexing to where
                   1204:    // the controller information should be placed.
                   1205:    //
                   1206:    ULONG ControllerSlot;
                   1207: 
                   1208:    //
                   1209:    // Short hand for referencing the particular controller config
                   1210:    // information that we are building up.
                   1211:    //
                   1212:    PCONFIG_CONTROLLER_DATA controller;
                   1213: 
                   1214:    PCM_FULL_RESOURCE_DESCRIPTOR peripheralData = (PCM_FULL_RESOURCE_DESCRIPTOR)
                   1215:       (((PUCHAR)PeripheralInformation[IoQueryDeviceConfigurationData]) +
                   1216:       PeripheralInformation[IoQueryDeviceConfigurationData]->DataOffset);
                   1217: 
                   1218:    //
                   1219:    // These three boolean will tell us whether we got all the
                   1220:    // information that we needed.
                   1221:    //
                   1222:    BOOLEAN foundPort = FALSE;
                   1223:    BOOLEAN foundInterrupt = FALSE;
                   1224:    BOOLEAN foundDma = FALSE;
                   1225: 
                   1226:    ASSERT(ControllerType == DiskController);
                   1227:    ASSERT(PeripheralType == FloppyDiskPeripheral);
                   1228: 
                   1229:    //
                   1230:    // Loop through the "slots" that we have for a new controller.
                   1231:    // Determine if this is a controller that we've already seen,
                   1232:    // or a new controller.
                   1233:    //
                   1234: 
                   1235:    outOfRoom = TRUE;
                   1236:    for (
                   1237:       ControllerSlot = 0;
                   1238:       ControllerSlot < MAXIMUM_CONTROLLERS_PER_MACHINE;
                   1239:       ControllerSlot++
                   1240:       ) {
                   1241: 
                   1242:       if (config->Controller[ControllerSlot].ActualControllerNumber == -1) {
                   1243: 
                   1244:             newController = TRUE;
                   1245:             outOfRoom = FALSE;
                   1246:             config->Controller[ControllerSlot].ActualControllerNumber =
                   1247:                ControllerNumber;
                   1248:             config->NumberOfControllers++;
                   1249:             break;
                   1250: 
                   1251:       } else if (config->Controller[ControllerSlot].ActualControllerNumber
                   1252:                   == (LONG)ControllerNumber) {
                   1253: 
                   1254:             newController = FALSE;
                   1255:             outOfRoom = FALSE;
                   1256:             break;
                   1257: 
                   1258:       }
                   1259: 
                   1260:    }
                   1261: 
                   1262:    if (outOfRoom) {
                   1263: 
                   1264:       //
                   1265:       // Just return and ignore the controller.
                   1266:       //
                   1267: 
                   1268:       return STATUS_SUCCESS;
                   1269: 
                   1270:    }
                   1271: 
                   1272:    controller = &config->Controller[ControllerSlot];
                   1273: 
                   1274:    if (newController) {
                   1275: 
                   1276:       PCM_FULL_RESOURCE_DESCRIPTOR controllerData =
                   1277:             (PCM_FULL_RESOURCE_DESCRIPTOR)
                   1278:             (((PUCHAR)ControllerInformation[IoQueryDeviceConfigurationData]) +
                   1279:             ControllerInformation[IoQueryDeviceConfigurationData]->DataOffset);
                   1280: 
                   1281:       //
                   1282:       // We have the pointer. Save off the interface type and
                   1283:       // the busnumber for use when we call the Hal and the
                   1284:       // Io System.
                   1285:       //
                   1286: 
                   1287:       controller->InterfaceType = BusType;
                   1288:       controller->BusNumber = BusNumber;
                   1289:       controller->SharableVector = TRUE;
                   1290:       controller->SaveFloatState = FALSE;
                   1291: 
                   1292:       //
                   1293:       // We need to get the following information out of the partial
                   1294:       // resource descriptors.
                   1295:       //
                   1296:       // The irql and vector.
                   1297:       //
                   1298:       // The dma channel.
                   1299:       //
                   1300:       // The base address and span covered by the floppy controllers
                   1301:       // registers.
                   1302:       //
                   1303:       // It is not defined how these appear in the partial resource
                   1304:       // lists, so we will just loop over all of them.    If we find
                   1305:       // something we don't recognize, we drop that information on
                   1306:       // the floor.   When we have finished going through all the
                   1307:       // partial information, we validate that we got the above
                   1308:       // three.
                   1309:       //
                   1310: 
                   1311:       CheckedDump(QIC117INFO,("Q117i: adding controller: %x slot: %x\n",ControllerNumber,ControllerSlot));
                   1312: 
                   1313:       for (
                   1314:             i = 0;
                   1315:             i < controllerData->PartialResourceList.Count;
                   1316:             i++
                   1317:             ) {
                   1318: 
                   1319:             PCM_PARTIAL_RESOURCE_DESCRIPTOR partial =
                   1320:                &controllerData->PartialResourceList.PartialDescriptors[i];
                   1321: 
                   1322:             switch (partial->Type) {
                   1323: 
                   1324:                case CmResourceTypePort: {
                   1325: 
                   1326:                   BOOLEAN inIoSpace =
                   1327: #ifdef i386
                   1328:                               TRUE;
                   1329: #else
                   1330:                               FALSE;
                   1331: #endif
                   1332: 
                   1333:                   foundPort = TRUE;
                   1334: 
                   1335:                   //
                   1336:                   // Save of the pointer to the partial so
                   1337:                   // that we can later use it to report resources
                   1338:                   // and we can also use this later in the routine
                   1339:                   // to make sure that we got all of our resources.
                   1340:                   //
                   1341: 
                   1342:                   controller->SpanOfControllerAddress =
                   1343:                         partial->u.Port.Length;
                   1344:                   controller->OriginalBaseAddress =
                   1345:                         partial->u.Port.Start;
                   1346:                   controller->ControllerBaseAddress = (PTAPE_ADDRESS)
                   1347:                         Q117iGetControllerBase(
                   1348:                            BusType,
                   1349:                            BusNumber,
                   1350:                            partial->u.Port.Start,
                   1351:                            controller->SpanOfControllerAddress,
                   1352:                            inIoSpace,
                   1353:                            &controller->MappedAddress
                   1354:                            );
                   1355: 
                   1356:                   if (!controller->ControllerBaseAddress) {
                   1357: 
                   1358:                         return STATUS_INSUFFICIENT_RESOURCES;
                   1359: 
                   1360:                   }
                   1361: 
                   1362:                   break;
                   1363:                }
                   1364:                case CmResourceTypeInterrupt: {
                   1365: 
                   1366:                   foundInterrupt = TRUE;
                   1367:                   if (partial->Flags & CM_RESOURCE_INTERRUPT_LATCHED) {
                   1368: 
                   1369:                         controller->InterruptMode = Latched;
                   1370: 
                   1371:                   } else {
                   1372: 
                   1373:                         controller->InterruptMode = LevelSensitive;
                   1374: 
                   1375:                   }
                   1376: 
                   1377:                   controller->OriginalIrql =  partial->u.Interrupt.Level;
                   1378:                   controller->OriginalVector = partial->u.Interrupt.Vector;
                   1379:                   controller->ControllerVector =
                   1380:                         HalGetInterruptVector(
                   1381:                            BusType,
                   1382:                            BusNumber,
                   1383:                            partial->u.Interrupt.Level,
                   1384:                            partial->u.Interrupt.Vector,
                   1385:                            &controller->ControllerIrql,
                   1386:                            &controller->ProcessorMask
                   1387:                            );
                   1388: 
                   1389:                   break;
                   1390:                }
                   1391:                case CmResourceTypeDma: {
                   1392: 
                   1393:                   DEVICE_DESCRIPTION deviceDesc;
                   1394: 
                   1395:                   RtlZeroMemory(&deviceDesc,sizeof(deviceDesc));
                   1396:                   foundDma = TRUE;
                   1397: 
                   1398:                   controller->OriginalDmaChannel = partial->u.Dma.Channel;
                   1399: 
                   1400:                   deviceDesc.Version = DEVICE_DESCRIPTION_VERSION;
                   1401:                   deviceDesc.DmaWidth = Width8Bits;
                   1402:                   deviceDesc.DemandMode = TRUE;
                   1403:                   deviceDesc.MaximumLength = 32l*1024l;
                   1404:                   deviceDesc.AutoInitialize = FALSE;
                   1405:                   deviceDesc.ScatterGather = FALSE;
                   1406:                   deviceDesc.DmaChannel = partial->u.Dma.Channel;
                   1407:                   deviceDesc.InterfaceType = BusType;
                   1408:                   deviceDesc.DmaSpeed = TypeA;
                   1409:                   controller->NumberOfMapRegisters = BYTES_TO_PAGES(32l*1024l);
                   1410:                   controller->AdapterObject =
                   1411:                         HalGetAdapter(
                   1412:                            &deviceDesc,
                   1413:                            &controller->NumberOfMapRegisters
                   1414:                            );
                   1415: 
                   1416:                   CheckedDump(QIC117INFO,( "Q117i: Bus Type = %d\n",
                   1417:                         BusType ));
                   1418:                   CheckedDump(QIC117INFO,( "Q117i: Number of map registers = %d\n",
                   1419:                         controller->NumberOfMapRegisters ));
                   1420: 
                   1421:                   if (!controller->AdapterObject) {
                   1422: 
                   1423:                         return STATUS_INSUFFICIENT_RESOURCES;
                   1424: 
                   1425:                   }
                   1426: 
                   1427:                   break;
                   1428: 
                   1429:                }
                   1430:                default: {
                   1431: 
                   1432:                   break;
                   1433: 
                   1434:                }
                   1435: 
                   1436:             }
                   1437: 
                   1438:       }
                   1439: 
                   1440:       //
                   1441:       // If we didn't get all the information then we return
                   1442:       // insufficient resources.
                   1443:       //
                   1444: 
                   1445:       if ((!foundPort) ||
                   1446:             (!foundInterrupt) ||
                   1447:             (!foundDma)) {
                   1448: 
                   1449:             return STATUS_INSUFFICIENT_RESOURCES;
                   1450: 
                   1451:       }
                   1452:       controller->NumberOfTapeDrives++;
                   1453:       controller->OkToUseThisController = TRUE;
                   1454: 
                   1455:    }
                   1456: 
                   1457: 
                   1458:    return STATUS_SUCCESS;
                   1459: }
                   1460: 
                   1461: NTSTATUS
                   1462: Q117iGetConfigurationInformation(
                   1463:    OUT PCONFIG_DATA *ConfigData
                   1464:    )
                   1465: 
                   1466: /*++
                   1467: 
                   1468: Routine Description:
                   1469: 
                   1470:    This routine is called by DriverEntry() to get information about the
                   1471:    devices to be supported from configuration mangement and/or the
                   1472:    hardware architecture layer (HAL).
                   1473: 
                   1474: Arguments:
                   1475: 
                   1476:    ConfigData - a pointer to the pointer to a data structure that
                   1477:    describes the controllers and the drives attached to them
                   1478: 
                   1479: Return Value:
                   1480: 
                   1481:    Returns STATUS_SUCCESS unless there is no drive 0 or we didn't get
                   1482:    any configuration information.
                   1483:    NOTE: FUTURE return values may change when config mgr is finished.
                   1484: 
                   1485: --*/
                   1486: 
                   1487: {
                   1488:    INTERFACE_TYPE InterfaceType;
                   1489:    NTSTATUS Status;
                   1490:    ULONG i;
                   1491: 
                   1492:    *ConfigData = ExAllocatePool(
                   1493:                         PagedPool,
                   1494:                         sizeof(CONFIG_DATA)
                   1495:                         );
                   1496: 
                   1497:    if (!*ConfigData) {
                   1498: 
                   1499:       return STATUS_INSUFFICIENT_RESOURCES;
                   1500: 
                   1501:    }
                   1502: 
                   1503:    //
                   1504:    // Zero out the config structure and fill in the actual
                   1505:    // controller numbers with -1's so that the callback routine
                   1506:    // can recognize a new controller.
                   1507:    //
                   1508: 
                   1509:    RtlZeroMemory(
                   1510:       *ConfigData,
                   1511:       sizeof(CONFIG_DATA)
                   1512:       );
                   1513: 
                   1514:    for (
                   1515:       i = 0;
                   1516:       i < MAXIMUM_CONTROLLERS_PER_MACHINE;
                   1517:       i++
                   1518:       ) {
                   1519: 
                   1520:       (*ConfigData)->Controller[i].ActualControllerNumber = -1;
                   1521: 
                   1522:    }
                   1523: 
                   1524:    //
                   1525:    // Go through all of the various bus types looking for
                   1526:    // disk controllers.    The disk controller sections of the
                   1527:    // hardware registry only deal with the floppy drives.
                   1528:    // The callout routine that can get called will then
                   1529:    // look for information pertaining to a particular
                   1530:    // device on the controller.
                   1531:    //
                   1532: 
                   1533:    for (
                   1534:       InterfaceType = 0;
                   1535:       InterfaceType < MaximumInterfaceType;
                   1536:       InterfaceType++
                   1537:       ) {
                   1538: 
                   1539:       CONFIGURATION_TYPE Dc = DiskController;
                   1540:       CONFIGURATION_TYPE Fp = FloppyDiskPeripheral;
                   1541: 
                   1542:       Status = IoQueryDeviceDescription(
                   1543:                      &InterfaceType,
                   1544:                      NULL,
                   1545:                      &Dc,
                   1546:                      NULL,
                   1547:                      &Fp,
                   1548:                      NULL,
                   1549:                      Q117iConfigCallBack,
                   1550:                      *ConfigData
                   1551:                      );
                   1552: 
                   1553:       if (!NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND)) {
                   1554: 
                   1555:             ExFreePool(*ConfigData);
                   1556:             *ConfigData = NULL;
                   1557:             return Status;
                   1558: 
                   1559:       }
                   1560: 
                   1561:    }
                   1562: 
                   1563:    return STATUS_SUCCESS;
                   1564: }
                   1565: 
                   1566: NTSTATUS
                   1567: Q117iInitializeController(
                   1568:    IN PCONFIG_DATA ConfigData,
                   1569:    IN UCHAR ControllerNumber,
                   1570:    IN PDRIVER_OBJECT DriverObject,
                   1571:    IN PUNICODE_STRING RegistryPath
                   1572:    )
                   1573: 
                   1574: /*++
                   1575: 
                   1576: Routine Description:
                   1577: 
                   1578:    This routine is called at initialization time by DriverEntry() -
                   1579:    once for each controller that the configuration manager tells it we
                   1580:    have to support.
                   1581: 
                   1582:    When this routine is called, the configuration data has already been
                   1583:    filled in.
                   1584: 
                   1585: Arguments:
                   1586: 
                   1587:    ConfigData - a pointer to the structure that describes the
                   1588:    controller and the disks attached to it, as given to us by the
                   1589:    configuration manager.
                   1590: 
                   1591:    ControllerNumber - which controller in ConfigData we are
                   1592:    initializing.
                   1593: 
                   1594:    DriverObject - a pointer to the object that represents this device
                   1595:    driver.
                   1596: 
                   1597: Return Value:
                   1598: 
                   1599:    STATUS_SUCCESS if this controller and at least one of its disks were
                   1600:    initialized; an error otherwise.
                   1601: 
                   1602: --*/
                   1603: 
                   1604: {
                   1605:    PTAPE_CONTROLLER_DATA controllerData;
                   1606:    PVOID threadObject;
                   1607:    NTSTATUS ntStatus;
                   1608:    NTSTATUS ntStatus2;
                   1609:    HANDLE threadHandle = 0;
                   1610:    BOOLEAN partlySuccessful;
                   1611:    LARGE_INTEGER timeout;
                   1612:    UCHAR ntNameBuffer[256];
                   1613:    STRING ntNameString;
                   1614:    UNICODE_STRING ntUnicodeString;
                   1615: 
                   1616:    CheckedDump(QIC117INFO,( "Q117iInitializeController...\n" ));
                   1617: 
                   1618:    //
                   1619:    // This routine will take attempt to "append" the resources
                   1620:    // used by this controller into the resource map of the
                   1621:    // registry.    If there was a conflict with previously "declared"
                   1622:    // data, then this routine will return false, in which case we
                   1623:    // will NOT try to initialize this particular controller.
                   1624:    //
                   1625: 
                   1626:    if (!Q117iReportResources(
                   1627:             DriverObject,
                   1628:             ConfigData,
                   1629:             ControllerNumber
                   1630:             )) {
                   1631: 
                   1632:       return STATUS_INSUFFICIENT_RESOURCES;
                   1633: 
                   1634:    }
                   1635: 
                   1636:    //
                   1637:    // Allocate and zero-initialize data to describe this controller
                   1638:    //
                   1639: 
                   1640:    controllerData = (PTAPE_CONTROLLER_DATA) ExAllocatePool(
                   1641:       NonPagedPool,
                   1642:       sizeof( TAPE_CONTROLLER_DATA ) );
                   1643: 
                   1644:    if ( controllerData == NULL ) {
                   1645: 
                   1646:       return STATUS_INSUFFICIENT_RESOURCES;
                   1647:    }
                   1648: 
                   1649:    RtlZeroMemory( controllerData, sizeof( TAPE_CONTROLLER_DATA ) );
                   1650: 
                   1651:    (VOID) sprintf(
                   1652:       ntNameBuffer,
                   1653:       "\\Device\\FloppyControllerEvent%d",
                   1654:       ControllerNumber );
                   1655: 
                   1656:    RtlInitString( &ntNameString, ntNameBuffer );
                   1657: 
                   1658:    ntStatus = RtlAnsiStringToUnicodeString(
                   1659:       &ntUnicodeString,
                   1660:       &ntNameString,
                   1661:       TRUE );
                   1662: 
                   1663:    controllerData->ControllerEvent = IoCreateSynchronizationEvent(
                   1664:       &ntUnicodeString,
                   1665:       &controllerData->ControllerEventHandle);
                   1666: 
                   1667:    RtlFreeUnicodeString( &ntUnicodeString );
                   1668: 
                   1669:    if ( controllerData->ControllerEvent == NULL ) {
                   1670:       return STATUS_INSUFFICIENT_RESOURCES;
                   1671:    }
                   1672: 
                   1673:    //
                   1674:    // Fill in some items that we got from configuration management and
                   1675:    // the HAL.
                   1676:    //
                   1677: 
                   1678:    controllerData->FDC_Addr = (PTAPE_ADDRESS)
                   1679:       ConfigData->Controller[ControllerNumber].ControllerBaseAddress;
                   1680:    controllerData->InterfaceType =
                   1681:       ConfigData->Controller[ControllerNumber].InterfaceType;
                   1682:    controllerData->ActualControllerNumber =
                   1683:       ConfigData->Controller[ControllerNumber].ActualControllerNumber;
                   1684: 
                   1685:    controllerData->DriveSelect.Selected = FALSE;
                   1686:    controllerData->DriveSelect.DeselectByte = dselb;
                   1687:    controllerData->DriveSelect.SelectByte = selb;
                   1688: 
                   1689:    ntStatus = IoConnectInterrupt(
                   1690:       (PKINTERRUPT *) &controllerData->InterruptObject,
                   1691:       (PKSERVICE_ROUTINE) Q117iTapeInterruptService,
                   1692:       (PVOID) controllerData,
                   1693:       (PKSPIN_LOCK)NULL,
                   1694:       ConfigData->Controller[ControllerNumber].ControllerVector,
                   1695:       ConfigData->Controller[ControllerNumber].ControllerIrql,
                   1696:       ConfigData->Controller[ControllerNumber].ControllerIrql,
                   1697:       ConfigData->Controller[ControllerNumber].InterruptMode,
                   1698:       ConfigData->Controller[ControllerNumber].SharableVector,
                   1699:       ConfigData->Controller[ControllerNumber].ProcessorMask,
                   1700:       ConfigData->Controller[ControllerNumber].SaveFloatState);
                   1701: 
                   1702: 
                   1703:    if ( NT_SUCCESS( ntStatus ) ) {
                   1704:       //
                   1705:       // Initialize the interlocked request queue, including a
                   1706:       // counting semaphore to indicate items in the queue
                   1707:       //
                   1708: 
                   1709:       KeInitializeSemaphore(
                   1710:             &controllerData->RequestSemaphore,
                   1711:             0L,
                   1712:             MAXLONG );
                   1713: 
                   1714:       KeInitializeSpinLock( &controllerData->ListSpinLock );
                   1715: 
                   1716:       InitializeListHead( &controllerData->ListEntry );
                   1717: 
                   1718:       //
                   1719:       // Initialize events to signal interrupts and adapter object
                   1720:       // allocation
                   1721:       //
                   1722: 
                   1723:       KeInitializeEvent(
                   1724:             &controllerData->InterruptEvent,
                   1725:             SynchronizationEvent,
                   1726:             FALSE);
                   1727: 
                   1728: 
                   1729:       KeInitializeEvent(
                   1730:             &controllerData->AllocateAdapterChannelEvent,
                   1731:             NotificationEvent,
                   1732:             FALSE );
                   1733: 
                   1734: 
                   1735:       KeInitializeEvent(
                   1736:             &controllerData->ClearQueueEvent,
                   1737:             SynchronizationEvent,
                   1738:             FALSE);
                   1739: 
                   1740: 
                   1741: 
                   1742:       //
                   1743:       // Create a thread with entry point Q117iTapeThread()
                   1744:       //
                   1745: 
                   1746:       ntStatus = PsCreateSystemThread(
                   1747:             &threadHandle,
                   1748:             (ACCESS_MASK) 0L,
                   1749:             (POBJECT_ATTRIBUTES) NULL,
                   1750:             (HANDLE) 0L,
                   1751:             (PCLIENT_ID) NULL,
                   1752:             (PKSTART_ROUTINE) Q117iTapeThread,
                   1753:             (PVOID) controllerData );
                   1754: 
                   1755: #if DBG
                   1756:       if ( !NT_SUCCESS( ntStatus ) ) {
                   1757: 
                   1758:             CheckedDump(QIC117DBGP,( "q117i: error %x creating thread\n", ntStatus ));
                   1759:       }
                   1760: #endif
                   1761: 
                   1762:       if ( NT_SUCCESS( ntStatus ) ) {
                   1763: 
                   1764:             CheckedDump(QIC117INFO,("Q117iThread = %x\n",threadHandle));
                   1765: 
                   1766:             //
                   1767:             // Call Q117iInitializeDrive() for each drive on the
                   1768:             // controller
                   1769:             //
                   1770: 
                   1771:             ConfigData->Controller[ControllerNumber].NumberOfTapeDrives++;
                   1772: 
                   1773:             ntStatus = STATUS_NO_SUCH_DEVICE;
                   1774:             partlySuccessful = FALSE;
                   1775: 
                   1776:             ntStatus = Q117iInitializeDrive(
                   1777:                ConfigData,
                   1778:                controllerData,
                   1779:                ControllerNumber,
                   1780:                DriverObject,
                   1781:                RegistryPath );
                   1782:       }
                   1783: 
                   1784:    }
                   1785: 
                   1786:    //
                   1787:    // If we're exiting with an error, clean up first.
                   1788:    //
                   1789: 
                   1790:    if ( !NT_SUCCESS( ntStatus ) ) {
                   1791: 
                   1792:       CheckedDump(QIC117DBGP,( "q117i: InitializeController failing\n" ));
                   1793: 
                   1794:       //
                   1795:       // If we created the thread, wake it up and tell it to kill itself.
                   1796:       // Wait until it's dead.    (Note that since it's a system thread,
                   1797:       // it has to kill itself - we can't do it).
                   1798:       //
                   1799: 
                   1800:       if ( threadHandle != 0 ) {
                   1801: 
                   1802:             controllerData->UnloadingDriver = TRUE;
                   1803: 
                   1804:             ntStatus2 = ObReferenceObjectByHandle(
                   1805:                threadHandle,
                   1806:                THREAD_ALL_ACCESS,
                   1807:                NULL,
                   1808:                KernelMode,
                   1809:                (PVOID *) &threadObject,
                   1810:                NULL );
                   1811: 
                   1812:             (VOID) KeReleaseSemaphore(
                   1813:                &controllerData->RequestSemaphore,
                   1814:                (KPRIORITY) 0,
                   1815:                1,
                   1816:                FALSE );
                   1817: 
                   1818:             if ( NT_SUCCESS( ntStatus2 ) ) {
                   1819: 
                   1820:                //
                   1821:                // The thread object will be signalled when it dies.
                   1822:                //
                   1823: 
                   1824:                ntStatus2 = KeWaitForSingleObject(
                   1825:                   (PVOID) threadObject,
                   1826:                   Suspended,
                   1827:                   KernelMode,
                   1828:                   FALSE,
                   1829:                   (PLARGE_INTEGER) NULL );
                   1830: 
                   1831:                ASSERT( ntStatus2 == STATUS_SUCCESS );
                   1832: 
                   1833:                ObDereferenceObject( threadObject );
                   1834: 
                   1835:             } else {
                   1836: 
                   1837:                //
                   1838:                // We can't get the thread object for some reason; just
                   1839:                // block for a while to give the thread a chance to run
                   1840:                // and die.
                   1841:                //
                   1842: 
                   1843:                CheckedDump(QIC117DBGP,( "q117i: couldn't get thread object\n" ));
                   1844: 
                   1845: 
                   1846:                timeout =
                   1847:                   RtlLargeIntegerNegate(
                   1848:                   RtlEnlargedIntegerMultiply(
                   1849:                         10,
                   1850:                         10l * 1000l
                   1851:                   )
                   1852:                );
                   1853:                (VOID) KeDelayExecutionThread(
                   1854:                   KernelMode,
                   1855:                   FALSE,
                   1856:                   &timeout );
                   1857:             }
                   1858:       }
                   1859: 
                   1860: 
                   1861:       if ( controllerData->InterruptObject != NULL ) {
                   1862: 
                   1863:           (VOID) KeSetEvent(
                   1864:                     controllerData->ControllerEvent,
                   1865:                     (KPRIORITY) 0,
                   1866:                     FALSE );
                   1867: 
                   1868:           IoDisconnectInterrupt( controllerData->InterruptObject );
                   1869:       }
                   1870: 
                   1871:       ExFreePool( controllerData );
                   1872: 
                   1873:    }
                   1874: 
                   1875:    return ntStatus;
                   1876: }
                   1877: 
                   1878: BOOLEAN
                   1879: Q117iReportResources(
                   1880:    IN PDRIVER_OBJECT DriverObject,
                   1881:    IN PCONFIG_DATA ConfigData,
                   1882:    IN UCHAR ControllerNumber
                   1883:    )
                   1884: 
                   1885: /*++
                   1886: 
                   1887: Routine Description:
                   1888: 
                   1889:    This routine will build up a resource list using the
                   1890:    data for this particular controller as well as all
                   1891:    previous *successfully* configured controllers.
                   1892: 
                   1893:    N.B.  This routine assumes that it called in controller
                   1894:    number order.
                   1895: 
                   1896: Arguments:
                   1897: 
                   1898:    DriverObject - a pointer to the object that represents this device
                   1899:    driver.
                   1900: 
                   1901:    ConfigData - a pointer to the structure that describes the
                   1902:    controller and the disks attached to it, as given to us by the
                   1903:    configuration manager.
                   1904: 
                   1905:    ControllerNumber - which controller in ConfigData we are
                   1906:    about to try to report.
                   1907: 
                   1908: Return Value:
                   1909: 
                   1910:    TRUE if no conflict was detected, FALSE otherwise.
                   1911: 
                   1912: --*/
                   1913: 
                   1914: {
                   1915: 
                   1916: 
                   1917:    ULONG sizeOfResourceList;
                   1918:    ULONG numberOfFrds;
                   1919:    LONG i;
                   1920:    PCM_RESOURCE_LIST resourceList;
                   1921:    PCM_FULL_RESOURCE_DESCRIPTOR nextFrd;
                   1922: 
                   1923:    //
                   1924:    // Loop through all of the controllers previous to this
                   1925:    // controller.  If the controllers previous to this one
                   1926:    // didn't have a conflict, then accumulate the size of the
                   1927:    // CM_FULL_RESOURCE_DESCRIPTOR associated with it.
                   1928:    //
                   1929: 
                   1930:    for (
                   1931:       i = 0,numberOfFrds = 0,sizeOfResourceList = 0;
                   1932:       i <= ControllerNumber;
                   1933:       i++
                   1934:       ) {
                   1935: 
                   1936:       if (ConfigData->Controller[i].OkToUseThisController) {
                   1937: 
                   1938:             sizeOfResourceList += sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
                   1939: 
                   1940:             //
                   1941:             // The full resource descriptor already contains one
                   1942:             // partial.  Make room for three more.
                   1943:             //
                   1944:             // It will hold the irq "prd", the controller "csr" "prd" which
                   1945:             // is actually in two pieces since we don't use one of the
                   1946:             // registers, and the controller dma "prd".
                   1947:             //
                   1948: 
                   1949:             sizeOfResourceList += 3*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
                   1950:             numberOfFrds++;
                   1951: 
                   1952:       }
                   1953: 
                   1954:    }
                   1955: 
                   1956:    //
                   1957:    // Now we increment the length of the resource list by field offset
                   1958:    // of the first frd.   This will give us the length of what preceeds
                   1959:    // the first frd in the resource list.
                   1960:    //
                   1961: 
                   1962:    sizeOfResourceList += FIELD_OFFSET(
                   1963:                               CM_RESOURCE_LIST,
                   1964:                               List[0]
                   1965:                               );
                   1966: 
                   1967:    resourceList = ExAllocatePool(
                   1968:                      PagedPool,
                   1969:                      sizeOfResourceList
                   1970:                      );
                   1971: 
                   1972:    if (!resourceList) {
                   1973: 
                   1974:       return FALSE;
                   1975: 
                   1976:    }
                   1977: 
                   1978:    //
                   1979:    // Zero out the field
                   1980:    //
                   1981: 
                   1982:    RtlZeroMemory(
                   1983:       resourceList,
                   1984:       sizeOfResourceList
                   1985:       );
                   1986: 
                   1987:    resourceList->Count = numberOfFrds;
                   1988:    nextFrd = &resourceList->List[0];
                   1989: 
                   1990:    for (
                   1991:       i = 0;
                   1992:       numberOfFrds;
                   1993:       i++
                   1994:       ) {
                   1995: 
                   1996:       if (ConfigData->Controller[i].OkToUseThisController) {
                   1997: 
                   1998:             PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
                   1999: 
                   2000:             nextFrd->InterfaceType = ConfigData->Controller[i].InterfaceType;
                   2001:             nextFrd->BusNumber = ConfigData->Controller[i].BusNumber;
                   2002: 
                   2003:             //
                   2004:             // We are only going to report 4 items no matter what
                   2005:             // was in the original.
                   2006:             //
                   2007: 
                   2008:             nextFrd->PartialResourceList.Count = 4;
                   2009: 
                   2010:             //
                   2011:             // Now fill in the port data.  We don't wish to share
                   2012:             // this port range with anyone
                   2013:             //
                   2014: 
                   2015:             partial = &nextFrd->PartialResourceList.PartialDescriptors[0];
                   2016: 
                   2017:             partial->Type = CmResourceTypePort;
                   2018:             partial->ShareDisposition = CmResourceShareShared;
                   2019:             partial->Flags = 0;
                   2020:             partial->u.Port.Start =
                   2021:                ConfigData->Controller[i].OriginalBaseAddress;
                   2022:             partial->u.Port.Length = 6;
                   2023: 
                   2024:             partial++;
                   2025: 
                   2026:             partial->Type = CmResourceTypePort;
                   2027:             partial->ShareDisposition = CmResourceShareShared;
                   2028:             partial->Flags = 0;
                   2029:             partial->u.Port.Start = RtlLargeIntegerAdd(
                   2030:                         ConfigData->Controller[i].OriginalBaseAddress,
                   2031:                         RtlConvertUlongToLargeInteger((ULONG)7)
                   2032:                         );
                   2033:             partial->u.Port.Length = 1;
                   2034: 
                   2035:             partial++;
                   2036: 
                   2037:             partial->Type = CmResourceTypeDma;
                   2038:             partial->ShareDisposition = CmResourceShareShared;
                   2039:             partial->Flags = 0;
                   2040:             partial->u.Dma.Channel =
                   2041:                ConfigData->Controller[i].OriginalDmaChannel;
                   2042: 
                   2043:             partial++;
                   2044: 
                   2045:             //
                   2046:             // Now fill in the irq stuff.
                   2047:             //
                   2048: 
                   2049:             partial->Type = CmResourceTypeInterrupt;
                   2050:             partial->ShareDisposition = CmResourceShareShared;
                   2051:             partial->u.Interrupt.Level =
                   2052:                ConfigData->Controller[i].OriginalIrql;
                   2053:             partial->u.Interrupt.Vector =
                   2054:                ConfigData->Controller[i].OriginalVector;
                   2055: 
                   2056:             if (ConfigData->Controller[i].InterruptMode == Latched) {
                   2057: 
                   2058:                partial->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
                   2059: 
                   2060:             } else {
                   2061: 
                   2062:                partial->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
                   2063: 
                   2064:             }
                   2065: 
                   2066:             partial++;
                   2067: 
                   2068:             nextFrd = (PVOID)partial;
                   2069: 
                   2070:             numberOfFrds--;
                   2071: 
                   2072:       }
                   2073: 
                   2074:    }
                   2075: 
                   2076:    IoReportResourceUsage(
                   2077:       NULL,
                   2078:       DriverObject,
                   2079:       resourceList,
                   2080:       sizeOfResourceList,
                   2081:       NULL,
                   2082:       NULL,
                   2083:       0,
                   2084:       FALSE,
                   2085:       &ConfigData->Controller[ControllerNumber].OkToUseThisController
                   2086:       );
                   2087: 
                   2088:    //
                   2089:    // The above routine sets the boolean the parameter
                   2090:    // to TRUE if a conflict was detected.
                   2091:    //
                   2092: 
                   2093:    ConfigData->Controller[ControllerNumber].OkToUseThisController =
                   2094:       !ConfigData->Controller[ControllerNumber].OkToUseThisController;
                   2095: 
                   2096:    ExFreePool(resourceList);
                   2097: 
                   2098:    return ConfigData->Controller[ControllerNumber].OkToUseThisController;
                   2099: 
                   2100: }
                   2101: 
                   2102: NTSTATUS
                   2103: Q117iInitializeDrive(
                   2104:    IN PCONFIG_DATA ConfigData,
                   2105:    IN PTAPE_CONTROLLER_DATA ControllerData,
                   2106:    IN UCHAR ControllerNum,
                   2107:    IN PDRIVER_OBJECT DriverObject,
                   2108:    IN PUNICODE_STRING RegistryPath
                   2109:    )
                   2110: 
                   2111: /*++
                   2112: 
                   2113: Routine Description:
                   2114: 
                   2115:    This routine is called at initialization time by
                   2116:    Q117iInitializeController(), once for each disk that we are supporting
                   2117:    on the controller.
                   2118: 
                   2119: Arguments:
                   2120: 
                   2121:    ConfigData - a pointer to the structure that describes the
                   2122:    controller and the disks attached to it, as given to us by the
                   2123:    configuration manager.
                   2124: 
                   2125:    ControllerData - a pointer to our data area for this controller.
                   2126: 
                   2127:    ControllerNum - which controller in ConfigData we're working on.
                   2128: 
                   2129:    DisketteNum - which logical disk on the current controller we're
                   2130:    working on.
                   2131: 
                   2132:    DisketteUnit - which physical disk on the current controller we're
                   2133:    working on. Only different from DisketteNum when we're creating a
                   2134:    secondary device object for a previously initialized drive.
                   2135: 
                   2136:    DriverObject - a pointer to the object that represents this device
                   2137:    driver.
                   2138: 
                   2139: Return Value:
                   2140: 
                   2141:    STATUS_SUCCESS if this disk is initialized; an error otherwise.
                   2142: 
                   2143: --*/
                   2144: 
                   2145: {
                   2146:    UCHAR ntNameBuffer[256];
                   2147:    STRING ntNameString;
                   2148:    UNICODE_STRING ntUnicodeString;
                   2149:    NTSTATUS ntStatus;
                   2150:    PDEVICE_OBJECT deviceObject = NULL;
                   2151:    PTAPE_EXTENSION tapeExtension;
                   2152:    STATUS retval;
                   2153: 
                   2154:    CheckedDump(QIC117INFO,( "Q117iInitializeDrive...\n" ));
                   2155: 
                   2156:    (VOID) sprintf(
                   2157:       ntNameBuffer,
                   2158:       "\\Device\\q117i%d", ConfigData->FloppyTapeCount);
                   2159: 
                   2160:    RtlInitString( &ntNameString, ntNameBuffer );
                   2161: 
                   2162:    ntStatus = RtlAnsiStringToUnicodeString(
                   2163:       &ntUnicodeString,
                   2164:       &ntNameString,
                   2165:       TRUE );
                   2166: 
                   2167:    if ( NT_SUCCESS( ntStatus ) ) {
                   2168: 
                   2169:       //
                   2170:       // Create a device object for this floppy drive.
                   2171:       //
                   2172: 
                   2173:       ntStatus = IoCreateDevice(
                   2174:             DriverObject,
                   2175:             sizeof( TAPE_EXTENSION ),
                   2176:             &ntUnicodeString,
                   2177:             FILE_DEVICE_TAPE,
                   2178:             FILE_REMOVABLE_MEDIA,
                   2179:             FALSE,
                   2180:             &deviceObject );
                   2181: 
                   2182:       RtlFreeUnicodeString(&ntUnicodeString);
                   2183: 
                   2184:    }
                   2185: 
                   2186: 
                   2187: 
                   2188:    if ( NT_SUCCESS( ntStatus ) ) {
                   2189: 
                   2190:       IoInitializeDpcRequest( deviceObject, Q117iTapeDeferredProcedure );
                   2191: 
                   2192:       tapeExtension = deviceObject->DeviceExtension;
                   2193:       tapeExtension->SpeedChangeOK = FALSE;
                   2194:       tapeExtension->PegasusSupported = TRUE;
                   2195:       tapeExtension->Found = FALSE;
                   2196:       tapeExtension->NoCart = TRUE;
                   2197:       tapeExtension->ErrorSequence = 0;
                   2198:       tapeExtension->TapeNumber = IoGetConfigurationInformation()->TapeCount;
                   2199:       tapeExtension->DriveParms.Mode = PRIMARY_MODE;
                   2200:       tapeExtension->DriveParms.Flavor = (UCHAR) UNKNOWN;
                   2201:       tapeExtension->QDeviceObject = deviceObject;
                   2202:       tapeExtension->QControllerData = ControllerData;
                   2203:       tapeExtension->QControllerData->StartFormatMode = FALSE;
                   2204:       tapeExtension->QControllerData->EndFormatMode = FALSE;
                   2205:       tapeExtension->QControllerData->ClearQueue = FALSE;
                   2206:       tapeExtension->QControllerData->AbortRequested = FALSE;
                   2207:       tapeExtension->QControllerData->AdapterLocked = FALSE;
                   2208:       tapeExtension->QControllerData->PerpendicularMode = FALSE;
                   2209:       tapeExtension->XferRate.XferRate = SLOW;
                   2210:       tapeExtension->XferRate.TapeSlow = TAPE_250Kbps;
                   2211:       tapeExtension->XferRate.TapeFast = TAPE_500Kbps;
                   2212:       tapeExtension->XferRate.FDC_Slow = FDC_250Kbps;
                   2213:       tapeExtension->XferRate.FDC_Fast = FDC_500Kbps;
                   2214:       tapeExtension->XferRate.SRT_Slow = SRT_250Kbps;
                   2215:       tapeExtension->XferRate.SRT_Fast = SRT_500Kbps;
                   2216: 
                   2217:       tapeExtension->QControllerData->AdapterObject =
                   2218:             ConfigData->Controller[ControllerNum].AdapterObject;
                   2219: 
                   2220:       tapeExtension->QControllerData->NumberOfMapRegisters =
                   2221:             ConfigData->Controller[ControllerNum].NumberOfMapRegisters;
                   2222: 
                   2223:       tapeExtension->QControllerData->TapeExtension = tapeExtension;
                   2224: 
                   2225: #if DBG
                   2226:       tapeExtension->DbgHead = tapeExtension->DbgTail = 0;
                   2227: #endif
                   2228: 
                   2229:       tapeExtension->QControllerData->CurrentInterrupt = TRUE;
                   2230: 
                   2231: 
                   2232:                retval = Q117iDLocateDrv(tapeExtension);
                   2233: 
                   2234:       tapeExtension->PersistentNewCart = FALSE;
                   2235:       ntStatus = Q117iTranslateError( deviceObject, retval );
                   2236:       tapeExtension->PersistentNewCart = TRUE;
                   2237: 
                   2238:       tapeExtension->QControllerData->CurrentInterrupt = FALSE;
                   2239:    }
                   2240: 
                   2241:    //
                   2242:    // Initialize the filer level tape device
                   2243:    //
                   2244: 
                   2245:    if ( NT_SUCCESS( ntStatus ) ) {
                   2246: 
                   2247:       ntStatus = q117Initialize(
                   2248:                         DriverObject,
                   2249:                         deviceObject,
                   2250:                         RegistryPath,
                   2251:                         ConfigData->Controller[ControllerNum].AdapterObject,
                   2252:                         ConfigData->Controller[ControllerNum].NumberOfMapRegisters
                   2253:                         );
                   2254: 
                   2255:    }
                   2256: 
                   2257:    if ( NT_SUCCESS( ntStatus ) ) {
                   2258: 
                   2259:       ConfigData->FloppyTapeCount++;
                   2260: 
                   2261:    } else {
                   2262: 
                   2263:       //
                   2264:       // If we're failing, clean up and delete the device object.
                   2265:       //
                   2266: 
                   2267:      CheckedDump(QIC117DBGP,( "Q117i: InitializeDrive failing %x\n", ntStatus ));
                   2268: 
                   2269:       if ( deviceObject != NULL ) {
                   2270: 
                   2271:             IoDeleteDevice( deviceObject );
                   2272:       }
                   2273:    }
                   2274: 
                   2275:    return ntStatus;
                   2276: }
                   2277: 
                   2278: ULONG
                   2279: Q117iGetControllerBase(
                   2280:    IN INTERFACE_TYPE BusType,
                   2281:    IN ULONG BusNumber,
                   2282:    PHYSICAL_ADDRESS IoAddress,
                   2283:    ULONG NumberOfBytes,
                   2284:    BOOLEAN InIoSpace,
                   2285:    PBOOLEAN MappedAddress
                   2286:    )
                   2287: 
                   2288: /*++
                   2289: 
                   2290: Routine Description:
                   2291: 
                   2292:    This routine maps an IO address to system address space.
                   2293: 
                   2294: Arguments:
                   2295: 
                   2296:    BusType - what type of bus - eisa, mca, isa
                   2297:    IoBusNumber - which IO bus (for machines with multiple buses).
                   2298:    IoAddress - base device address to be mapped.
                   2299:    NumberOfBytes - number of bytes for which address is valid.
                   2300:    InIoSpace - indicates an IO address.
                   2301:    MappedAddress - indicates whether the address was mapped.
                   2302:                   This only has meaning if the address returned
                   2303:                   is non-null.
                   2304: 
                   2305: Return Value:
                   2306: 
                   2307:    Mapped address
                   2308: 
                   2309: --*/
                   2310: 
                   2311: {
                   2312:    PHYSICAL_ADDRESS cardAddress;
                   2313:    ULONG addressSpace = InIoSpace;
                   2314:    ULONG Address;
                   2315: 
                   2316:    HalTranslateBusAddress(
                   2317:             BusType,
                   2318:             BusNumber,
                   2319:             IoAddress,
                   2320:             &addressSpace,
                   2321:             &cardAddress
                   2322:             );
                   2323: 
                   2324:    //
                   2325:    // Map the device base address into the virtual address space
                   2326:    // if the address is in memory space.
                   2327:    //
                   2328: 
                   2329:    if (!addressSpace) {
                   2330: 
                   2331:       Address = (ULONG)MmMapIoSpace(
                   2332:                         cardAddress,
                   2333:                         NumberOfBytes,
                   2334:                         FALSE
                   2335:                         );
                   2336: 
                   2337:       *MappedAddress = (BOOLEAN)((Address)?(TRUE):(FALSE));
                   2338: 
                   2339: 
                   2340:    } else {
                   2341: 
                   2342:       Address = (ULONG)cardAddress.LowPart;
                   2343:    }
                   2344: 
                   2345:    return Address;
                   2346: 
                   2347: }
                   2348: 

unix.superglobalmegacorp.com

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