|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.